Core/Algorithm: Add SafeCast
This commit is contained in:
parent
73838f5f08
commit
66bbf63e87
|
|
@ -715,7 +715,7 @@ int main()
|
|||
builder.BindVertexBuffer(0, *cubeMeshGfx->GetVertexBuffer(0));
|
||||
builder.BindPipeline(*skyboxPipeline);
|
||||
|
||||
builder.DrawIndexed(static_cast<Nz::UInt32>(cubeMeshGfx->GetIndexCount(0)));
|
||||
builder.DrawIndexed(Nz::SafeCast<Nz::UInt32>(cubeMeshGfx->GetIndexCount(0)));
|
||||
});
|
||||
forwardPass.SetExecutionCallback([&]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ namespace Nz
|
|||
template<typename T> void HashCombine(std::size_t& seed, const T& v);
|
||||
template<typename T> bool IsPowerOfTwo(T value);
|
||||
template<typename T> T ReverseBits(T integer);
|
||||
#ifdef NAZARA_DEBUG
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To> && std::is_integral_v<From>, int> = 0> To SafeCast(From value);
|
||||
template<typename To, typename From, std::enable_if_t<std::is_floating_point_v<To> && std::is_floating_point_v<From>, int> = 0> To SafeCast(From value);
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To> && std::is_floating_point_v<From>, int> = 0> To SafeCast(From value);
|
||||
template<typename To, typename From, std::enable_if_t<std::is_floating_point_v<To> && std::is_integral_v<From>, int> = 0> To SafeCast(From value);
|
||||
template<typename To, typename From, std::enable_if_t<std::is_enum_v<To>&& std::is_integral_v<From>, int> = 0> To SafeCast(From value);
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To>&& std::is_enum_v<From>, int> = 0> To SafeCast(From value);
|
||||
#else
|
||||
template<typename To, typename From> To SafeCast(From value);
|
||||
#endif
|
||||
template<typename T> constexpr auto UnderlyingCast(T value) -> std::underlying_type_t<T>;
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <Nazara/Core/Stream.hpp>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
|
|
@ -291,6 +292,75 @@ namespace Nz
|
|||
return reversed;
|
||||
}
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To> && std::is_integral_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
// Type capable of storing the biggest value between the two types
|
||||
using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v<To>)), From, To>;
|
||||
// Type capable of storing the smallest value between the two types
|
||||
using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v<From>)), From, To>;
|
||||
|
||||
if constexpr (!std::is_signed_v<To>)
|
||||
assert(value >= 0);
|
||||
|
||||
assert(static_cast<MaxValueType>(value) <= static_cast<MaxValueType>(std::numeric_limits<To>::max()));
|
||||
assert(static_cast<MinValueType>(value) >= static_cast<MinValueType>(std::numeric_limits<To>::lowest()));
|
||||
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
template<typename To, typename From, std::enable_if_t<std::is_floating_point_v<To> && std::is_floating_point_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
// Type capable of storing the biggest value between the two types
|
||||
using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>;
|
||||
// Type capable of storing the smallest value between the two types
|
||||
using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>;
|
||||
|
||||
assert(static_cast<MaxValueType>(value) <= static_cast<MaxValueType>(std::numeric_limits<To>::max()));
|
||||
assert(static_cast<MinValueType>(value) >= static_cast<MinValueType>(std::numeric_limits<To>::lowest()));
|
||||
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To> && std::is_floating_point_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
assert(floor(value) == value);
|
||||
|
||||
assert(value <= static_cast<From>(std::numeric_limits<To>::max()));
|
||||
assert(value >= static_cast<From>(std::numeric_limits<To>::lowest()));
|
||||
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
template<typename To, typename From, std::enable_if_t<std::is_floating_point_v<To> && std::is_integral_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
|
||||
template<typename To, typename From, std::enable_if_t<std::is_enum_v<To> && std::is_integral_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
return static_cast<To>(SafeCast<std::underlying_type_t<To>>(value));
|
||||
}
|
||||
|
||||
template<typename To, typename From, std::enable_if_t<std::is_integral_v<To> && std::is_enum_v<From>, int>>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
return SafeCast<To>(static_cast<std::underlying_type_t<From>>(value));
|
||||
}
|
||||
|
||||
#else
|
||||
template<typename To, typename From>
|
||||
To SafeCast(From value)
|
||||
{
|
||||
return static_cast<To>(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr auto UnderlyingCast(T value) -> std::underlying_type_t<T>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/RenderElement.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline RenderElement::RenderElement(BasicRenderElement elementType) :
|
||||
RenderElement(static_cast<UInt8>(elementType))
|
||||
RenderElement(SafeCast<UInt8>(elementType))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -22,3 +24,5 @@ namespace Nz
|
|||
return m_elementType;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ namespace Nz
|
|||
std::array<Vector2f, circleVerticesCount> vertices;
|
||||
|
||||
Vector2f origin = FromChipmunk(pos);
|
||||
float r = static_cast<float>(radius);
|
||||
float r = SafeCast<float>(radius);
|
||||
|
||||
RadianAnglef angleBetweenVertices = 2.f * Pi<float> / vertices.size();
|
||||
for (std::size_t i = 0; i < vertices.size(); ++i)
|
||||
|
|
@ -91,7 +91,7 @@ namespace Nz
|
|||
{
|
||||
const auto& callback = *static_cast<const CallbackType*>(userdata);
|
||||
|
||||
static std::pair<float, float> sincos = Nz::DegreeAnglef(90.f).GetSinCos();
|
||||
static std::pair<float, float> sincos = DegreeAnglef(90.f).GetSinCos();
|
||||
|
||||
Vector2f from = FromChipmunk(a);
|
||||
Vector2f to = FromChipmunk(b);
|
||||
|
|
@ -100,7 +100,7 @@ namespace Nz
|
|||
Vector2f thicknessNormal(sincos.second * normal.x - sincos.first * normal.y,
|
||||
sincos.first * normal.x + sincos.second * normal.y);
|
||||
|
||||
float thickness = static_cast<float>(radius);
|
||||
float thickness = SafeCast<float>(radius);
|
||||
|
||||
std::array<Vector2f, 4> vertices;
|
||||
vertices[0] = from + thickness * thicknessNormal;
|
||||
|
|
@ -166,14 +166,14 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
Nz::Vector2f BoxCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f BoxCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
return m_rect.GetCenter();
|
||||
}
|
||||
|
||||
float BoxCollider2D::ComputeMomentOfInertia(float mass) const
|
||||
{
|
||||
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
|
||||
return SafeCast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
|
||||
}
|
||||
|
||||
ColliderType2D BoxCollider2D::GetType() const
|
||||
|
|
@ -195,14 +195,14 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
Nz::Vector2f CircleCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f CircleCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
float CircleCollider2D::ComputeMomentOfInertia(float mass) const
|
||||
{
|
||||
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
|
||||
return SafeCast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
|
||||
}
|
||||
|
||||
ColliderType2D CircleCollider2D::GetType() const
|
||||
|
|
@ -224,9 +224,9 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
Nz::Vector2f CompoundCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f CompoundCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
Nz::Vector2f centerOfMass = Nz::Vector2f::Zero();
|
||||
Vector2f centerOfMass = Vector2f::Zero();
|
||||
for (const auto& geom : m_geoms)
|
||||
centerOfMass += geom->ComputeCenterOfMass();
|
||||
|
||||
|
|
@ -285,20 +285,20 @@ namespace Nz
|
|||
m_vertices[i].Set(*vertices++);
|
||||
}
|
||||
|
||||
Nz::Vector2f ConvexCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f ConvexCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
|
||||
|
||||
cpVect center = cpCentroidForPoly(int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()));
|
||||
|
||||
return Nz::Vector2f(float(center.x), float(center.y));
|
||||
return Vector2f(float(center.x), float(center.y));
|
||||
}
|
||||
|
||||
float ConvexCollider2D::ComputeMomentOfInertia(float mass) const
|
||||
{
|
||||
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
|
||||
|
||||
return static_cast<float>(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()), cpv(0.0, 0.0), m_radius));
|
||||
return SafeCast<float>(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()), cpv(0.0, 0.0), m_radius));
|
||||
}
|
||||
|
||||
ColliderType2D ConvexCollider2D::GetType() const
|
||||
|
|
@ -319,9 +319,9 @@ namespace Nz
|
|||
return ColliderType2D::Null;
|
||||
}
|
||||
|
||||
Nz::Vector2f NullCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f NullCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
return Nz::Vector2f::Zero();
|
||||
return Vector2f::Zero();
|
||||
}
|
||||
|
||||
float NullCollider2D::ComputeMomentOfInertia(float mass) const
|
||||
|
|
@ -336,14 +336,14 @@ namespace Nz
|
|||
|
||||
/******************************** SegmentCollider2D *********************************/
|
||||
|
||||
Nz::Vector2f SegmentCollider2D::ComputeCenterOfMass() const
|
||||
Vector2f SegmentCollider2D::ComputeCenterOfMass() const
|
||||
{
|
||||
return (m_first + m_second) / 2.f;
|
||||
}
|
||||
|
||||
float SegmentCollider2D::ComputeMomentOfInertia(float mass) const
|
||||
{
|
||||
return static_cast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
|
||||
return SafeCast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
|
||||
}
|
||||
|
||||
ColliderType2D SegmentCollider2D::GetType() const
|
||||
|
|
|
|||
|
|
@ -145,38 +145,38 @@ namespace Nz
|
|||
|
||||
std::shared_ptr<StaticMesh> Collider3D::GenerateMesh() const
|
||||
{
|
||||
std::vector<Nz::Vector3f> colliderVertices;
|
||||
std::vector<Nz::UInt16> colliderIndices;
|
||||
std::vector<Vector3f> colliderVertices;
|
||||
std::vector<UInt16> colliderIndices;
|
||||
|
||||
// Generate a line list
|
||||
ForEachPolygon([&](const Nz::Vector3f* vertices, std::size_t vertexCount)
|
||||
ForEachPolygon([&](const Vector3f* vertices, std::size_t vertexCount)
|
||||
{
|
||||
Nz::UInt16 firstIndex = colliderVertices.size();
|
||||
UInt16 firstIndex = SafeCast<UInt16>(colliderVertices.size());
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
colliderVertices.push_back(vertices[i]);
|
||||
|
||||
for (std::size_t i = 1; i < vertexCount; ++i)
|
||||
{
|
||||
colliderIndices.push_back(firstIndex + i - 1);
|
||||
colliderIndices.push_back(firstIndex + i);
|
||||
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + i - 1));
|
||||
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + i));
|
||||
}
|
||||
|
||||
if (vertexCount > 2)
|
||||
{
|
||||
colliderIndices.push_back(firstIndex + vertexCount - 1);
|
||||
colliderIndices.push_back(firstIndex);
|
||||
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + vertexCount - 1));
|
||||
colliderIndices.push_back(SafeCast<UInt16>(firstIndex));
|
||||
}
|
||||
});
|
||||
|
||||
std::shared_ptr<Nz::VertexBuffer> colliderVB = std::make_shared<Nz::VertexBuffer>(Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ), colliderVertices.size(), Nz::DataStorage::Software, 0);
|
||||
std::shared_ptr<VertexBuffer> colliderVB = std::make_shared<VertexBuffer>(VertexDeclaration::Get(VertexLayout::XYZ), colliderVertices.size(), DataStorage::Software, 0);
|
||||
colliderVB->Fill(colliderVertices.data(), 0, colliderVertices.size());
|
||||
|
||||
std::shared_ptr<Nz::IndexBuffer> colliderIB = std::make_shared<Nz::IndexBuffer>(false, colliderIndices.size(), Nz::DataStorage::Software, 0);
|
||||
std::shared_ptr<IndexBuffer> colliderIB = std::make_shared<IndexBuffer>(false, colliderIndices.size(), DataStorage::Software, 0);
|
||||
colliderIB->Fill(colliderIndices.data(), 0, colliderIndices.size());
|
||||
|
||||
std::shared_ptr<Nz::StaticMesh> colliderSubMesh = std::make_shared<Nz::StaticMesh>(std::move(colliderVB), std::move(colliderIB));
|
||||
std::shared_ptr<StaticMesh> colliderSubMesh = std::make_shared<StaticMesh>(std::move(colliderVB), std::move(colliderIB));
|
||||
colliderSubMesh->GenerateAABB();
|
||||
colliderSubMesh->SetPrimitiveMode(Nz::PrimitiveMode::LineList);
|
||||
colliderSubMesh->SetPrimitiveMode(PrimitiveMode::LineList);
|
||||
|
||||
return colliderSubMesh;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue