Merge remote-tracking branch 'refs/remotes/origin/master' into culling

This commit is contained in:
Lynix
2016-10-19 11:17:12 +02:00
151 changed files with 3726 additions and 1373 deletions

View File

@@ -65,7 +65,7 @@ namespace Nz
* \return true If replication is enabled
*/
bool FileLogger::IsStdReplicationEnabled()
bool FileLogger::IsStdReplicationEnabled() const
{
return m_stdReplicationEnabled;
}
@@ -75,7 +75,7 @@ namespace Nz
* \return true If logging of the time is enabled
*/
bool FileLogger::IsTimeLoggingEnabled()
bool FileLogger::IsTimeLoggingEnabled() const
{
return m_timeLoggingEnabled;
}
@@ -147,14 +147,6 @@ namespace Nz
void FileLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (m_forceStdOutput || m_stdReplicationEnabled)
{
m_stdLogger.WriteError(type, error, line, file, function);
if (m_forceStdOutput)
return;
}
AbstractLogger::WriteError(type, error, line, file, function);
m_outputFile.Flush();
}

View File

@@ -111,7 +111,9 @@ namespace Nz
bool Log::Initialize()
{
SetLogger(new FileLogger());
if (s_logger == &s_stdLogger)
SetLogger(new FileLogger());
return true;
}

View File

@@ -208,8 +208,9 @@ namespace Nz
time_t FileImpl::GetCreationTime(const String& filePath)
{
NazaraWarning("Posix has no creation time information");
NazaraUnused(filePath);
NazaraWarning("Posix has no creation time information");
return 0;
}

View File

@@ -47,7 +47,7 @@ namespace Nz
* \return Always returns true
*/
bool StdLogger::IsStdReplicationEnabled()
bool StdLogger::IsStdReplicationEnabled() const
{
return true;
}

View File

@@ -82,7 +82,7 @@ namespace Nz
if (pipelineEntry.maxInstanceCount > 0)
{
bool instancing = (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
bool instancing = instancingEnabled && (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
UInt32 flags = ShaderFlags_Deferred;
if (instancing)

View File

@@ -282,7 +282,6 @@ namespace Nz
{
for (auto& pipelinePair : layer.opaqueModels)
{
const MaterialPipeline* pipeline = pipelinePair.first;
auto& pipelineEntry = pipelinePair.second;
if (pipelineEntry.maxInstanceCount > 0)

View File

@@ -52,7 +52,7 @@ namespace Nz
{
ErrorFlags flags(ErrorFlag_ThrowException, true);
std::array<UInt8, 4> whitePixel = {255, 255, 255, 255};
std::array<UInt8, 4> whitePixel = { {255, 255, 255, 255} };
m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1);
m_whiteTexture.Update(whitePixel.data());
@@ -431,7 +431,6 @@ namespace Nz
for (auto& matIt : pipelinePair.second.materialMap)
{
const Material* material = matIt.first;
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
@@ -551,9 +550,7 @@ namespace Nz
const MeshData& meshData = meshIt.first;
auto& meshEntry = meshIt.second;
const Spheref& squaredBoundingSphere = meshEntry.squaredBoundingSphere;
std::vector<Matrix4f>& instances = meshEntry.instances;
if (!instances.empty())
{
const IndexBuffer* indexBuffer = meshData.indexBuffer;

View File

@@ -560,9 +560,7 @@ namespace Nz
auto& overlayMap = matEntry.overlayMap;
for (auto& overlayIt : overlayMap)
{
const Texture* overlay = overlayIt.first;
auto& spriteChainVector = overlayIt.second.spriteChains;
spriteChainVector.clear();
}
@@ -581,9 +579,7 @@ namespace Nz
{
for (auto& materialPair : pipelineEntry.materialMap)
{
const Material* material = materialPair.first;
auto& matEntry = materialPair.second;
if (matEntry.enabled)
{
MeshInstanceContainer& meshInstances = matEntry.meshMap;
@@ -591,7 +587,6 @@ namespace Nz
for (auto& meshIt : meshInstances)
{
auto& meshEntry = meshIt.second;
meshEntry.instances.clear();
}
matEntry.enabled = false;

View File

@@ -53,7 +53,7 @@ namespace Nz
{
ErrorFlags flags(ErrorFlag_ThrowException, true);
std::array<UInt8, 4> whitePixel = {255, 255, 255, 255};
std::array<UInt8, 4> whitePixel = { {255, 255, 255, 255} };
m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1);
m_whiteTexture.Update(whitePixel.data());
@@ -412,7 +412,7 @@ namespace Nz
const Shader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
if (Renderer::HasCapability(RendererCap_Instancing))
if (m_instancingEnabled && Renderer::HasCapability(RendererCap_Instancing))
{
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
@@ -508,7 +508,6 @@ namespace Nz
for (auto& matIt : pipelinePair.second.materialMap)
{
const Material* material = matIt.first;
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
@@ -591,7 +590,7 @@ namespace Nz
if (pipelineEntry.maxInstanceCount > 0)
{
bool instancing = (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
bool instancing = m_instancingEnabled && (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply((instancing) ? ShaderFlags_Instancing : 0);
const Shader* shader = pipelineInstance.uberInstance->GetShader();

View File

@@ -85,7 +85,7 @@ namespace Nz
}
m_activeSockets.clear();
if (activeSockets > 0U)
if (activeSockets > 0)
{
int socketCount = activeSockets;
for (int i = 0; i < socketCount; ++i)

View File

@@ -54,7 +54,7 @@ namespace Nz
byteToInt hostOrder;
hostOrder.i = ntohl(addr.s_addr);
return { hostOrder.b[3], hostOrder.b[2], hostOrder.b[1], hostOrder.b[0] };
return { {hostOrder.b[3], hostOrder.b[2], hostOrder.b[1], hostOrder.b[0]} };
}
IpAddress::IPv6 convertSockaddr6ToIPv6(const in6_addr& addr)

View File

@@ -74,7 +74,7 @@ namespace Nz
activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast<int>(msTimeout), error);
m_activeSockets.clear();
if (activeSockets > 0U)
if (activeSockets > 0)
{
int socketRemaining = activeSockets;
for (PollSocket& entry : m_sockets)

View File

@@ -51,11 +51,12 @@ namespace Nz
d[2] = d[0] + Vector2f(1.f - 2.f * s_UnskewCoeff2D);
Vector2i offset(skewedCubeOrigin.x & 255, skewedCubeOrigin.y & 255);
std::array<std::size_t, 3> gi =
{
m_permutations[offset.x + m_permutations[offset.y]] & 7,
m_permutations[offset.x + off1.x + m_permutations[offset.y + off1.y]] & 7,
m_permutations[offset.x + 1 + m_permutations[offset.y + 1]] & 7
std::array<std::size_t, 3> gi = {
{
m_permutations[offset.x + m_permutations[offset.y]] & 7,
m_permutations[offset.x + off1.x + m_permutations[offset.y + off1.y]] & 7,
m_permutations[offset.x + 1 + m_permutations[offset.y + 1]] & 7
}
};
float n = 0.f;

View File

@@ -12,12 +12,13 @@ namespace Nz
{
namespace
{
static constexpr std::array<float, 4> m_functionScales =
{
1.f / float(M_SQRT2),
0.5f / float(M_SQRT2),
0.5f / float(M_SQRT2),
0.5f / float(M_SQRT2)
static constexpr std::array<float, 4> m_functionScales = {
{
1.f / float(M_SQRT2),
0.5f / float(M_SQRT2),
0.5f / float(M_SQRT2),
0.5f / float(M_SQRT2)
}
};
}
Worley::Worley() :
@@ -109,12 +110,12 @@ namespace Nz
return it->first * m_functionScales[functionIndex];
}
float Worley::Get(float x, float y, float z, float scale) const
float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*scale*/) const
{
throw std::runtime_error("Worley 3D not available yet.");
}
float Worley::Get(float x, float y, float z, float w, float scale) const
float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*w*/, float /*scale*/) const
{
throw std::runtime_error("Worley 4D not available yet.");
}

View File

@@ -1,448 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics/Geom.hpp>
#include <Nazara/Physics/PhysWorld.hpp>
#include <Newton/Newton.h>
#include <memory>
#include <Nazara/Physics/Debug.hpp>
namespace Nz
{
namespace
{
PhysGeomRef CreateGeomFromPrimitive(const Primitive& primitive)
{
switch (primitive.type)
{
case PrimitiveType_Box:
return BoxGeom::New(primitive.box.lengths, primitive.matrix);
case PrimitiveType_Cone:
return ConeGeom::New(primitive.cone.length, primitive.cone.radius, primitive.matrix);
case PrimitiveType_Plane:
return BoxGeom::New(Vector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix);
///TODO: PlaneGeom?
case PrimitiveType_Sphere:
return SphereGeom::New(primitive.sphere.size, primitive.matrix.GetTranslation());
}
NazaraError("Primitive type not handled (0x" + String::Number(primitive.type, 16) + ')');
return PhysGeomRef();
}
}
PhysGeom::~PhysGeom()
{
for (auto& pair : m_handles)
NewtonDestroyCollision(pair.second);
}
Boxf PhysGeom::ComputeAABB(const Vector3f& translation, const Quaternionf& rotation, const Vector3f& scale) const
{
return ComputeAABB(Matrix4f::Transform(translation, rotation), scale);
}
Boxf PhysGeom::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f min, max;
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld world;
NewtonCollision* collision = CreateHandle(&world);
{
NewtonCollisionCalculateAABB(collision, offsetMatrix, min, max);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
NewtonCollisionCalculateAABB(m_handles.begin()->second, offsetMatrix, min, max);
return Boxf(scale * min, scale * max);
}
void PhysGeom::ComputeInertialMatrix(Vector3f* inertia, Vector3f* center) const
{
float inertiaMatrix[3];
float origin[3];
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld world;
NewtonCollision* collision = CreateHandle(&world);
{
NewtonConvexCollisionCalculateInertialMatrix(collision, inertiaMatrix, origin);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
NewtonConvexCollisionCalculateInertialMatrix(m_handles.begin()->second, inertiaMatrix, origin);
if (inertia)
inertia->Set(inertiaMatrix);
if (center)
center->Set(origin);
}
float PhysGeom::ComputeVolume() const
{
float volume;
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld world;
NewtonCollision* collision = CreateHandle(&world);
{
volume = NewtonConvexCollisionCalculateVolume(collision);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
volume = NewtonConvexCollisionCalculateVolume(m_handles.begin()->second);
return volume;
}
NewtonCollision* PhysGeom::GetHandle(PhysWorld* world) const
{
auto it = m_handles.find(world);
if (it == m_handles.end())
it = m_handles.insert(std::make_pair(world, CreateHandle(world))).first;
return it->second;
}
PhysGeomRef PhysGeom::Build(const PrimitiveList& list)
{
std::size_t primitiveCount = list.GetSize();
if (primitiveCount > 1)
{
std::vector<PhysGeom*> geoms(primitiveCount);
for (unsigned int i = 0; i < primitiveCount; ++i)
geoms[i] = CreateGeomFromPrimitive(list.GetPrimitive(i));
return CompoundGeom::New(&geoms[0], primitiveCount);
}
else if (primitiveCount > 0)
return CreateGeomFromPrimitive(list.GetPrimitive(0));
else
return NullGeom::New();
}
bool PhysGeom::Initialize()
{
if (!PhysGeomLibrary::Initialize())
{
NazaraError("Failed to initialise library");
return false;
}
return true;
}
void PhysGeom::Uninitialize()
{
PhysGeomLibrary::Uninitialize();
}
PhysGeomLibrary::LibraryMap PhysGeom::s_library;
/********************************** BoxGeom **********************************/
BoxGeom::BoxGeom(const Vector3f& lengths, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_lengths(lengths)
{
}
BoxGeom::BoxGeom(const Vector3f& lengths, const Vector3f& translation, const Quaternionf& rotation) :
BoxGeom(lengths, Matrix4f::Transform(translation, rotation))
{
}
Boxf BoxGeom::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f halfLengths(m_lengths * 0.5f);
Boxf aabb(-halfLengths.x, -halfLengths.y, -halfLengths.z, m_lengths.x, m_lengths.y, m_lengths.z);
aabb.Transform(offsetMatrix, true);
aabb *= scale;
return aabb;
}
float BoxGeom::ComputeVolume() const
{
return m_lengths.x * m_lengths.y * m_lengths.z;
}
Vector3f BoxGeom::GetLengths() const
{
return m_lengths;
}
GeomType BoxGeom::GetType() const
{
return GeomType_Box;
}
NewtonCollision* BoxGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateBox(world->GetHandle(), m_lengths.x, m_lengths.y, m_lengths.z, 0, m_matrix);
}
/******************************** CapsuleGeom ********************************/
CapsuleGeom::CapsuleGeom(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
CapsuleGeom::CapsuleGeom(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
CapsuleGeom(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float CapsuleGeom::GetLength() const
{
return m_length;
}
float CapsuleGeom::GetRadius() const
{
return m_radius;
}
GeomType CapsuleGeom::GetType() const
{
return GeomType_Capsule;
}
NewtonCollision* CapsuleGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateCapsule(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/******************************* CompoundGeom ********************************/
CompoundGeom::CompoundGeom(PhysGeom** geoms, std::size_t geomCount)
{
m_geoms.reserve(geomCount);
for (std::size_t i = 0; i < geomCount; ++i)
m_geoms.emplace_back(geoms[i]);
}
const std::vector<PhysGeomRef>& CompoundGeom::GetGeoms() const
{
return m_geoms;
}
GeomType CompoundGeom::GetType() const
{
return GeomType_Compound;
}
NewtonCollision* CompoundGeom::CreateHandle(PhysWorld* world) const
{
NewtonCollision* compoundCollision = NewtonCreateCompoundCollision(world->GetHandle(), 0);
NewtonCompoundCollisionBeginAddRemove(compoundCollision);
for (const PhysGeomRef& geom : m_geoms)
{
if (geom->GetType() == GeomType_Compound)
{
CompoundGeom* compoundGeom = static_cast<CompoundGeom*>(geom.Get());
for (const PhysGeomRef& piece : compoundGeom->GetGeoms())
NewtonCompoundCollisionAddSubCollision(compoundCollision, piece->GetHandle(world));
}
else
NewtonCompoundCollisionAddSubCollision(compoundCollision, geom->GetHandle(world));
}
NewtonCompoundCollisionEndAddRemove(compoundCollision);
return compoundCollision;
}
/********************************* ConeGeom **********************************/
ConeGeom::ConeGeom(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
ConeGeom::ConeGeom(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
ConeGeom(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float ConeGeom::GetLength() const
{
return m_length;
}
float ConeGeom::GetRadius() const
{
return m_radius;
}
GeomType ConeGeom::GetType() const
{
return GeomType_Cone;
}
NewtonCollision* ConeGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateCone(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/****************************** ConvexHullGeom *******************************/
ConvexHullGeom::ConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_tolerance(tolerance),
m_vertexStride(stride)
{
const UInt8* ptr = static_cast<const UInt8*>(vertices);
m_vertices.resize(vertexCount);
if (stride != sizeof(Vector3f))
{
for (unsigned int i = 0; i < vertexCount; ++i)
m_vertices[i] = *reinterpret_cast<const Vector3f*>(ptr + stride*i);
}
else // Fast path
std::memcpy(m_vertices.data(), vertices, vertexCount*sizeof(Vector3f));
}
ConvexHullGeom::ConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const Vector3f& translation, const Quaternionf& rotation) :
ConvexHullGeom(vertices, vertexCount, stride, tolerance, Matrix4f::Transform(translation, rotation))
{
}
GeomType ConvexHullGeom::GetType() const
{
return GeomType_Compound;
}
NewtonCollision* ConvexHullGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateConvexHull(world->GetHandle(), static_cast<int>(m_vertices.size()), reinterpret_cast<const float*>(m_vertices.data()), sizeof(Vector3f), m_tolerance, 0, m_matrix);
}
/******************************* CylinderGeom ********************************/
CylinderGeom::CylinderGeom(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
CylinderGeom::CylinderGeom(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
CylinderGeom(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float CylinderGeom::GetLength() const
{
return m_length;
}
float CylinderGeom::GetRadius() const
{
return m_radius;
}
GeomType CylinderGeom::GetType() const
{
return GeomType_Cylinder;
}
NewtonCollision* CylinderGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateCylinder(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/********************************* NullGeom **********************************/
NullGeom::NullGeom()
{
}
GeomType NullGeom::GetType() const
{
return GeomType_Null;
}
void NullGeom::ComputeInertialMatrix(Vector3f* inertia, Vector3f* center) const
{
if (inertia)
inertia->MakeUnit();
if (center)
center->MakeZero();
}
NewtonCollision* NullGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateNull(world->GetHandle());
}
/******************************** SphereGeom *********************************/
SphereGeom::SphereGeom(float radius, const Matrix4f& transformMatrix) :
SphereGeom(radius, transformMatrix.GetTranslation())
{
}
SphereGeom::SphereGeom(float radius, const Vector3f& translation, const Quaternionf& rotation) :
m_position(translation),
m_radius(radius)
{
NazaraUnused(rotation);
}
Boxf SphereGeom::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f size(m_radius * NazaraSuffixMacro(M_SQRT3, f) * scale);
Vector3f position(offsetMatrix.GetTranslation());
return Boxf(position - size, position + size);
}
float SphereGeom::ComputeVolume() const
{
return float(M_PI) * m_radius * m_radius * m_radius / 3.f;
}
float SphereGeom::GetRadius() const
{
return m_radius;
}
GeomType SphereGeom::GetType() const
{
return GeomType_Sphere;
}
NewtonCollision* SphereGeom::CreateHandle(PhysWorld* world) const
{
return NewtonCreateSphere(world->GetHandle(), m_radius, 0, Matrix4f::Translate(m_position));
}
}

View File

@@ -0,0 +1,87 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Collider2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <chipmunk/chipmunk.h>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
Collider2D::~Collider2D() = default;
/******************************** BoxCollider2D *********************************/
BoxCollider2D::BoxCollider2D(const Vector2f& size, float radius) :
BoxCollider2D(Rectf(-size.x / 2.f, -size.y / 2.f, size.x / 2.f, size.y / 2.f), radius)
{
}
BoxCollider2D::BoxCollider2D(const Rectf& rect, float radius) :
m_rect(rect),
m_radius(radius)
{
}
float BoxCollider2D::ComputeInertialMatrix(float mass) const
{
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y + m_rect.height, m_rect.x + m_rect.width, m_rect.y)));
}
ColliderType2D BoxCollider2D::GetType() const
{
return ColliderType2D_Box;
}
std::vector<cpShape*> BoxCollider2D::CreateShapes(RigidBody2D* body) const
{
std::vector<cpShape*> shapes;
shapes.push_back(cpBoxShapeNew2(body->GetHandle(), cpBBNew(m_rect.x, m_rect.y + m_rect.height, m_rect.x + m_rect.width, m_rect.y), m_radius));
return shapes;
}
/******************************** CircleCollider2D *********************************/
CircleCollider2D::CircleCollider2D(float radius, const Vector2f& offset) :
m_offset(offset),
m_radius(radius)
{
}
float CircleCollider2D::ComputeInertialMatrix(float mass) const
{
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
}
ColliderType2D CircleCollider2D::GetType() const
{
return ColliderType2D_Circle;
}
std::vector<cpShape*> CircleCollider2D::CreateShapes(RigidBody2D* body) const
{
std::vector<cpShape*> shapes;
shapes.push_back(cpCircleShapeNew(body->GetHandle(), m_radius, cpv(m_offset.x, m_offset.y)));
return shapes;
}
/********************************* NullCollider2D **********************************/
ColliderType2D NullCollider2D::GetType() const
{
return ColliderType2D_Null;
}
float NullCollider2D::ComputeInertialMatrix(float /*mass*/) const
{
return 0.f;
}
std::vector<cpShape*> NullCollider2D::CreateShapes(RigidBody2D* /*body*/) const
{
return std::vector<cpShape*>();
}
}

View File

@@ -1,8 +1,8 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics module"
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics/Config.hpp>
#include <Nazara/Physics3D/Config.hpp>
#if NAZARA_PHYSICS_MANAGE_MEMORY
#include <Nazara/Core/MemoryManager.hpp>

View File

@@ -0,0 +1,60 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <chipmunk/chipmunk.h>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
PhysWorld2D::PhysWorld2D() :
m_stepSize(0.005f),
m_timestepAccumulator(0.f)
{
m_handle = cpSpaceNew();
cpSpaceSetUserData(m_handle, this);
}
PhysWorld2D::~PhysWorld2D()
{
cpSpaceFree(m_handle);
}
Vector2f PhysWorld2D::GetGravity() const
{
cpVect gravity = cpSpaceGetGravity(m_handle);
return Vector2f(gravity.x, gravity.y);
}
cpSpace* PhysWorld2D::GetHandle() const
{
return m_handle;
}
float PhysWorld2D::GetStepSize() const
{
return m_stepSize;
}
void PhysWorld2D::SetGravity(const Vector2f& gravity)
{
cpSpaceSetGravity(m_handle, cpv(gravity.x, gravity.y));
}
void PhysWorld2D::SetStepSize(float stepSize)
{
m_stepSize = stepSize;
}
void PhysWorld2D::Step(float timestep)
{
m_timestepAccumulator += timestep;
while (m_timestepAccumulator >= m_stepSize)
{
cpSpaceStep(m_handle, m_stepSize);
m_timestepAccumulator -= m_stepSize;
}
}
}

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Physics2D.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
bool Physics2D::Initialize()
{
if (s_moduleReferenceCounter > 0)
{
s_moduleReferenceCounter++;
return true; // Déjà initialisé
}
// Initialisation des dépendances
if (!Core::Initialize())
{
NazaraError("Failed to initialize core module");
return false;
}
s_moduleReferenceCounter++;
NazaraNotice("Initialized: Physics2D module");
return true;
}
bool Physics2D::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
void Physics2D::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
// Le module est soit encore utilisé, soit pas initialisé
if (s_moduleReferenceCounter > 1)
s_moduleReferenceCounter--;
return;
}
// Libération du module
s_moduleReferenceCounter = 0;
NazaraNotice("Uninitialized: Physics2D module");
// Libération des dépendances
Core::Uninitialize();
}
unsigned int Physics2D::s_moduleReferenceCounter = 0;
}

View File

@@ -0,0 +1,251 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <chipmunk/chipmunk.h>
#include <chipmunk/chipmunk_private.h>
#include <algorithm>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
RigidBody2D::RigidBody2D(PhysWorld2D* world, float mass) :
RigidBody2D(world, mass, nullptr)
{
}
RigidBody2D::RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom) :
m_geom(),
m_world(world),
m_gravityFactor(1.f),
m_mass(0.f)
{
NazaraAssert(m_world, "Invalid world");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
SetGeom(geom);
SetMass(mass);
}
RigidBody2D::RigidBody2D(const RigidBody2D& object) :
m_geom(object.m_geom),
m_world(object.m_world),
m_gravityFactor(object.m_gravityFactor),
m_mass(0.f)
{
NazaraAssert(m_world, "Invalid world");
NazaraAssert(m_geom, "Invalid geometry");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
SetGeom(object.GetGeom());
SetMass(object.GetMass());
}
RigidBody2D::RigidBody2D(RigidBody2D&& object) :
m_shapes(std::move(object.m_shapes)),
m_geom(std::move(object.m_geom)),
m_handle(object.m_handle),
m_world(object.m_world),
m_gravityFactor(object.m_gravityFactor),
m_mass(object.m_mass)
{
object.m_handle = nullptr;
}
RigidBody2D::~RigidBody2D()
{
Destroy();
}
void RigidBody2D::AddForce(const Vector2f& force, CoordSys coordSys)
{
return AddForce(force, GetCenterOfGravity(coordSys), coordSys);
}
void RigidBody2D::AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys)
{
switch (coordSys)
{
case CoordSys_Global:
cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(force.x, force.y));
break;
case CoordSys_Local:
cpBodyApplyForceAtLocalPoint(m_handle, cpv(force.x, force.y), cpv(point.x, point.y));
break;
}
}
void RigidBody2D::AddTorque(float torque)
{
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque);
}
Rectf RigidBody2D::GetAABB() const
{
cpBB bb = cpBBNew(0.f, 0.f, 0.f, 0.f);
for (cpShape* shape : m_shapes)
bb = cpBBMerge(bb, cpShapeGetBB(shape));
return Rectf(Rect<cpFloat>(bb.l, bb.t, bb.r - bb.l, bb.b - bb.t));
}
float RigidBody2D::GetAngularVelocity() const
{
return static_cast<float>(cpBodyGetAngularVelocity(m_handle));
}
const Collider2DRef& RigidBody2D::GetGeom() const
{
return m_geom;
}
cpBody* RigidBody2D::GetHandle() const
{
return m_handle;
}
float RigidBody2D::GetMass() const
{
return m_mass;
}
Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const
{
cpVect cog = cpBodyGetCenterOfGravity(m_handle);
switch (coordSys)
{
case CoordSys_Global:
cog = cpBodyLocalToWorld(m_handle, cog);
break;
case CoordSys_Local:
break; // Nothing to do
}
return Vector2f(static_cast<float>(cog.x), static_cast<float>(cog.y));
}
Vector2f RigidBody2D::GetPosition() const
{
cpVect pos = cpBodyGetPosition(m_handle);
return Vector2f(static_cast<float>(pos.x), static_cast<float>(pos.y));
}
float RigidBody2D::GetRotation() const
{
return static_cast<float>(cpBodyGetAngle(m_handle));
}
Vector2f RigidBody2D::GetVelocity() const
{
cpVect vel = cpBodyGetVelocity(m_handle);
return Vector2f(static_cast<float>(vel.x), static_cast<float>(vel.y));
}
bool RigidBody2D::IsMoveable() const
{
return m_mass > 0.f;
}
bool RigidBody2D::IsSleeping() const
{
return cpBodyIsSleeping(m_handle) != 0;
}
void RigidBody2D::SetAngularVelocity(float angularVelocity)
{
cpBodySetAngularVelocity(m_handle, angularVelocity);
}
void RigidBody2D::SetMass(float mass)
{
if (m_mass > 0.f)
{
if (mass > 0.f)
cpBodySetMass(m_handle, mass);
else
cpBodySetType(m_handle, CP_BODY_TYPE_STATIC);
}
else if (mass > 0.f)
{
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC);
}
m_mass = mass;
}
void RigidBody2D::SetMassCenter(const Vector2f& center)
{
if (m_mass > 0.f)
cpBodySetCenterOfGravity(m_handle, cpv(center.x, center.y));
}
void RigidBody2D::SetPosition(const Vector2f& position)
{
cpBodySetPosition(m_handle, cpv(position.x, position.y));
}
void RigidBody2D::SetRotation(float rotation)
{
cpBodySetAngle(m_handle, rotation);
}
void RigidBody2D::SetVelocity(const Vector2f& velocity)
{
cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y));
}
RigidBody2D& RigidBody2D::operator=(const RigidBody2D& object)
{
RigidBody2D physObj(object);
return operator=(std::move(physObj));
}
RigidBody2D& RigidBody2D::operator=(RigidBody2D&& object)
{
Destroy();
m_handle = object.m_handle;
m_geom = std::move(object.m_geom);
m_gravityFactor = object.m_gravityFactor;
m_mass = object.m_mass;
m_shapes = std::move(object.m_shapes);
m_world = object.m_world;
object.m_handle = nullptr;
return *this;
}
void RigidBody2D::Destroy()
{
for (cpShape* shape : m_shapes)
cpShapeFree(shape);
if (m_handle)
cpBodyFree(m_handle);
}
void RigidBody2D::SetGeom(Collider2DRef geom)
{
if (geom)
m_geom = geom;
else
m_geom = NullCollider2D::New();
m_shapes = m_geom->CreateShapes(this);
}
}

View File

@@ -0,0 +1,445 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics3D/Collider3D.hpp>
#include <Nazara/Physics3D/PhysWorld3D.hpp>
#include <Newton/Newton.h>
#include <memory>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
namespace
{
Collider3DRef CreateGeomFromPrimitive(const Primitive& primitive)
{
switch (primitive.type)
{
case PrimitiveType_Box:
return BoxCollider3D::New(primitive.box.lengths, primitive.matrix);
case PrimitiveType_Cone:
return ConeCollider3D::New(primitive.cone.length, primitive.cone.radius, primitive.matrix);
case PrimitiveType_Plane:
return BoxCollider3D::New(Vector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix);
///TODO: PlaneGeom?
case PrimitiveType_Sphere:
return SphereCollider3D::New(primitive.sphere.size, primitive.matrix.GetTranslation());
}
NazaraError("Primitive type not handled (0x" + String::Number(primitive.type, 16) + ')');
return Collider3DRef();
}
}
Collider3D::~Collider3D()
{
for (auto& pair : m_handles)
NewtonDestroyCollision(pair.second);
}
Boxf Collider3D::ComputeAABB(const Vector3f& translation, const Quaternionf& rotation, const Vector3f& scale) const
{
return ComputeAABB(Matrix4f::Transform(translation, rotation), scale);
}
Boxf Collider3D::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f min, max;
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld3D world;
NewtonCollision* collision = CreateHandle(&world);
{
NewtonCollisionCalculateAABB(collision, offsetMatrix, min, max);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
NewtonCollisionCalculateAABB(m_handles.begin()->second, offsetMatrix, min, max);
return Boxf(scale * min, scale * max);
}
void Collider3D::ComputeInertialMatrix(Vector3f* inertia, Vector3f* center) const
{
float inertiaMatrix[3];
float origin[3];
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld3D world;
NewtonCollision* collision = CreateHandle(&world);
{
NewtonConvexCollisionCalculateInertialMatrix(collision, inertiaMatrix, origin);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
NewtonConvexCollisionCalculateInertialMatrix(m_handles.begin()->second, inertiaMatrix, origin);
if (inertia)
inertia->Set(inertiaMatrix);
if (center)
center->Set(origin);
}
float Collider3D::ComputeVolume() const
{
float volume;
// Si nous n'avons aucune instance, nous en créons une temporaire
if (m_handles.empty())
{
PhysWorld3D world;
NewtonCollision* collision = CreateHandle(&world);
{
volume = NewtonConvexCollisionCalculateVolume(collision);
}
NewtonDestroyCollision(collision);
}
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
volume = NewtonConvexCollisionCalculateVolume(m_handles.begin()->second);
return volume;
}
NewtonCollision* Collider3D::GetHandle(PhysWorld3D* world) const
{
auto it = m_handles.find(world);
if (it == m_handles.end())
it = m_handles.insert(std::make_pair(world, CreateHandle(world))).first;
return it->second;
}
Collider3DRef Collider3D::Build(const PrimitiveList& list)
{
std::size_t primitiveCount = list.GetSize();
if (primitiveCount > 1)
{
std::vector<Collider3D*> geoms(primitiveCount);
for (unsigned int i = 0; i < primitiveCount; ++i)
geoms[i] = CreateGeomFromPrimitive(list.GetPrimitive(i));
return CompoundCollider3D::New(&geoms[0], primitiveCount);
}
else if (primitiveCount > 0)
return CreateGeomFromPrimitive(list.GetPrimitive(0));
else
return NullCollider3D::New();
}
bool Collider3D::Initialize()
{
if (!Collider3DLibrary::Initialize())
{
NazaraError("Failed to initialise library");
return false;
}
return true;
}
void Collider3D::Uninitialize()
{
Collider3DLibrary::Uninitialize();
}
Collider3DLibrary::LibraryMap Collider3D::s_library;
/********************************** BoxCollider3D **********************************/
BoxCollider3D::BoxCollider3D(const Vector3f& lengths, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_lengths(lengths)
{
}
BoxCollider3D::BoxCollider3D(const Vector3f& lengths, const Vector3f& translation, const Quaternionf& rotation) :
BoxCollider3D(lengths, Matrix4f::Transform(translation, rotation))
{
}
Boxf BoxCollider3D::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f halfLengths(m_lengths * 0.5f);
Boxf aabb(-halfLengths.x, -halfLengths.y, -halfLengths.z, m_lengths.x, m_lengths.y, m_lengths.z);
aabb.Transform(offsetMatrix, true);
aabb *= scale;
return aabb;
}
float BoxCollider3D::ComputeVolume() const
{
return m_lengths.x * m_lengths.y * m_lengths.z;
}
Vector3f BoxCollider3D::GetLengths() const
{
return m_lengths;
}
ColliderType3D BoxCollider3D::GetType() const
{
return ColliderType3D_Box;
}
NewtonCollision* BoxCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateBox(world->GetHandle(), m_lengths.x, m_lengths.y, m_lengths.z, 0, m_matrix);
}
/******************************** CapsuleCollider3D ********************************/
CapsuleCollider3D::CapsuleCollider3D(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
CapsuleCollider3D::CapsuleCollider3D(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
CapsuleCollider3D(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float CapsuleCollider3D::GetLength() const
{
return m_length;
}
float CapsuleCollider3D::GetRadius() const
{
return m_radius;
}
ColliderType3D CapsuleCollider3D::GetType() const
{
return ColliderType3D_Capsule;
}
NewtonCollision* CapsuleCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateCapsule(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/******************************* CompoundCollider3D ********************************/
CompoundCollider3D::CompoundCollider3D(Collider3D** geoms, std::size_t geomCount)
{
m_geoms.reserve(geomCount);
for (std::size_t i = 0; i < geomCount; ++i)
m_geoms.emplace_back(geoms[i]);
}
const std::vector<Collider3DRef>& CompoundCollider3D::GetGeoms() const
{
return m_geoms;
}
ColliderType3D CompoundCollider3D::GetType() const
{
return ColliderType3D_Compound;
}
NewtonCollision* CompoundCollider3D::CreateHandle(PhysWorld3D* world) const
{
NewtonCollision* compoundCollision = NewtonCreateCompoundCollision(world->GetHandle(), 0);
NewtonCompoundCollisionBeginAddRemove(compoundCollision);
for (const Collider3DRef& geom : m_geoms)
{
if (geom->GetType() == ColliderType3D_Compound)
{
CompoundCollider3D* compoundGeom = static_cast<CompoundCollider3D*>(geom.Get());
for (const Collider3DRef& piece : compoundGeom->GetGeoms())
NewtonCompoundCollisionAddSubCollision(compoundCollision, piece->GetHandle(world));
}
else
NewtonCompoundCollisionAddSubCollision(compoundCollision, geom->GetHandle(world));
}
NewtonCompoundCollisionEndAddRemove(compoundCollision);
return compoundCollision;
}
/********************************* ConeCollider3D **********************************/
ConeCollider3D::ConeCollider3D(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
ConeCollider3D::ConeCollider3D(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
ConeCollider3D(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float ConeCollider3D::GetLength() const
{
return m_length;
}
float ConeCollider3D::GetRadius() const
{
return m_radius;
}
ColliderType3D ConeCollider3D::GetType() const
{
return ColliderType3D_Cone;
}
NewtonCollision* ConeCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateCone(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/****************************** ConvexCollider3D *******************************/
ConvexCollider3D::ConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount, float tolerance, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_tolerance(tolerance)
{
m_vertices.resize(vertexCount);
if (vertices.GetStride() != sizeof(Vector3f))
{
for (unsigned int i = 0; i < vertexCount; ++i)
m_vertices[i] = *vertices++;
}
else // Fast path
std::memcpy(m_vertices.data(), vertices, vertexCount*sizeof(Vector3f));
}
ConvexCollider3D::ConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount, float tolerance, const Vector3f& translation, const Quaternionf& rotation) :
ConvexCollider3D(vertices, vertexCount, tolerance, Matrix4f::Transform(translation, rotation))
{
}
ColliderType3D ConvexCollider3D::GetType() const
{
return ColliderType3D_Compound;
}
NewtonCollision* ConvexCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateConvexHull(world->GetHandle(), static_cast<int>(m_vertices.size()), reinterpret_cast<const float*>(m_vertices.data()), sizeof(Vector3f), m_tolerance, 0, m_matrix);
}
/******************************* CylinderCollider3D ********************************/
CylinderCollider3D::CylinderCollider3D(float length, float radius, const Matrix4f& transformMatrix) :
m_matrix(transformMatrix),
m_length(length),
m_radius(radius)
{
}
CylinderCollider3D::CylinderCollider3D(float length, float radius, const Vector3f& translation, const Quaternionf& rotation) :
CylinderCollider3D(length, radius, Matrix4f::Transform(translation, rotation))
{
}
float CylinderCollider3D::GetLength() const
{
return m_length;
}
float CylinderCollider3D::GetRadius() const
{
return m_radius;
}
ColliderType3D CylinderCollider3D::GetType() const
{
return ColliderType3D_Cylinder;
}
NewtonCollision* CylinderCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateCylinder(world->GetHandle(), m_radius, m_length, 0, m_matrix);
}
/********************************* NullCollider3D **********************************/
NullCollider3D::NullCollider3D()
{
}
ColliderType3D NullCollider3D::GetType() const
{
return ColliderType3D_Null;
}
void NullCollider3D::ComputeInertialMatrix(Vector3f* inertia, Vector3f* center) const
{
if (inertia)
inertia->MakeUnit();
if (center)
center->MakeZero();
}
NewtonCollision* NullCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateNull(world->GetHandle());
}
/******************************** SphereCollider3D *********************************/
SphereCollider3D::SphereCollider3D(float radius, const Matrix4f& transformMatrix) :
SphereCollider3D(radius, transformMatrix.GetTranslation())
{
}
SphereCollider3D::SphereCollider3D(float radius, const Vector3f& translation, const Quaternionf& rotation) :
m_position(translation),
m_radius(radius)
{
NazaraUnused(rotation);
}
Boxf SphereCollider3D::ComputeAABB(const Matrix4f& offsetMatrix, const Vector3f& scale) const
{
Vector3f size(m_radius * NazaraSuffixMacro(M_SQRT3, f) * scale);
Vector3f position(offsetMatrix.GetTranslation());
return Boxf(position - size, position + size);
}
float SphereCollider3D::ComputeVolume() const
{
return float(M_PI) * m_radius * m_radius * m_radius / 3.f;
}
float SphereCollider3D::GetRadius() const
{
return m_radius;
}
ColliderType3D SphereCollider3D::GetType() const
{
return ColliderType3D_Sphere;
}
NewtonCollision* SphereCollider3D::CreateHandle(PhysWorld3D* world) const
{
return NewtonCreateSphere(world->GetHandle(), m_radius, 0, Matrix4f::Translate(m_position));
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics3D/Config.hpp>
#if NAZARA_PHYSICS_MANAGE_MEMORY
#include <Nazara/Core/MemoryManager.hpp>
#include <new> // Nécessaire ?
void* operator new(std::size_t size)
{
return Nz::MemoryManager::Allocate(size, false);
}
void* operator new[](std::size_t size)
{
return Nz::MemoryManager::Allocate(size, true);
}
void operator delete(void* pointer) noexcept
{
Nz::MemoryManager::Free(pointer, false);
}
void operator delete[](void* pointer) noexcept
{
Nz::MemoryManager::Free(pointer, true);
}
#endif // NAZARA_PHYSICS_MANAGE_MEMORY

View File

@@ -1,14 +1,14 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics module"
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics/PhysWorld.hpp>
#include <Nazara/Physics3D/PhysWorld3D.hpp>
#include <Newton/Newton.h>
#include <Nazara/Physics/Debug.hpp>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
PhysWorld::PhysWorld() :
PhysWorld3D::PhysWorld3D() :
m_gravity(Vector3f::Zero()),
m_stepSize(0.005f),
m_timestepAccumulator(0.f)
@@ -17,42 +17,42 @@ namespace Nz
NewtonWorldSetUserData(m_world, this);
}
PhysWorld::~PhysWorld()
PhysWorld3D::~PhysWorld3D()
{
NewtonDestroy(m_world);
}
Vector3f PhysWorld::GetGravity() const
Vector3f PhysWorld3D::GetGravity() const
{
return m_gravity;
}
NewtonWorld* PhysWorld::GetHandle() const
NewtonWorld* PhysWorld3D::GetHandle() const
{
return m_world;
}
float PhysWorld::GetStepSize() const
float PhysWorld3D::GetStepSize() const
{
return m_stepSize;
}
void PhysWorld::SetGravity(const Vector3f& gravity)
void PhysWorld3D::SetGravity(const Vector3f& gravity)
{
m_gravity = gravity;
}
void PhysWorld::SetSolverModel(unsigned int model)
void PhysWorld3D::SetSolverModel(unsigned int model)
{
NewtonSetSolverModel(m_world, model);
}
void PhysWorld::SetStepSize(float stepSize)
void PhysWorld3D::SetStepSize(float stepSize)
{
m_stepSize = stepSize;
}
void PhysWorld::Step(float timestep)
void PhysWorld3D::Step(float timestep)
{
m_timestepAccumulator += timestep;

View File

@@ -1,24 +1,24 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics module"
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics/Physics.hpp>
#include <Nazara/Physics3D/Physics3D.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Physics/Config.hpp>
#include <Nazara/Physics/Geom.hpp>
#include <Nazara/Physics3D/Config.hpp>
#include <Nazara/Physics3D/Collider3D.hpp>
#include <Newton/Newton.h>
#include <Nazara/Physics/Debug.hpp>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
unsigned int Physics::GetMemoryUsed()
unsigned int Physics3D::GetMemoryUsed()
{
return NewtonGetMemoryUsed();
}
bool Physics::Initialize()
bool Physics3D::Initialize()
{
if (s_moduleReferenceCounter > 0)
{
@@ -36,22 +36,22 @@ namespace Nz
s_moduleReferenceCounter++;
// Initialisation du module
if (!PhysGeom::Initialize())
if (!Collider3D::Initialize())
{
NazaraError("Failed to initialize geoms");
return false;
}
NazaraNotice("Initialized: Physics module");
NazaraNotice("Initialized: Physics3D module");
return true;
}
bool Physics::IsInitialized()
bool Physics3D::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
void Physics::Uninitialize()
void Physics3D::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
@@ -63,15 +63,15 @@ namespace Nz
}
// Libération du module
PhysGeom::Uninitialize();
Collider3D::Uninitialize();
s_moduleReferenceCounter = 0;
NazaraNotice("Uninitialized: Physics module");
NazaraNotice("Uninitialized: Physics3D module");
// Libération des dépendances
Core::Uninitialize();
}
unsigned int Physics::s_moduleReferenceCounter = 0;
unsigned int Physics3D::s_moduleReferenceCounter = 0;
}

View File

@@ -1,25 +1,25 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics module"
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics/PhysObject.hpp>
#include <Nazara/Physics3D/RigidBody3D.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Physics/Config.hpp>
#include <Nazara/Physics/PhysWorld.hpp>
#include <Nazara/Physics3D/Config.hpp>
#include <Nazara/Physics3D/PhysWorld3D.hpp>
#include <Newton/Newton.h>
#include <algorithm>
#include <Nazara/Physics/Debug.hpp>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
PhysObject::PhysObject(PhysWorld* world, const Matrix4f& mat) :
PhysObject(world, NullGeom::New(), mat)
RigidBody3D::RigidBody3D(PhysWorld3D* world, const Matrix4f& mat) :
RigidBody3D(world, NullCollider3D::New(), mat)
{
}
PhysObject::PhysObject(PhysWorld* world, PhysGeomRef geom, const Matrix4f& mat) :
m_matrix(mat),
RigidBody3D::RigidBody3D(PhysWorld3D* world, Collider3DRef geom, const Matrix4f& mat) :
m_geom(std::move(geom)),
m_matrix(mat),
m_forceAccumulator(Vector3f::Zero()),
m_torqueAccumulator(Vector3f::Zero()),
m_world(world),
@@ -29,15 +29,15 @@ namespace Nz
NazaraAssert(m_world, "Invalid world");
if (!m_geom)
m_geom = NullGeom::New();
m_geom = NullCollider3D::New();
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
NewtonBodySetUserData(m_body, this);
}
PhysObject::PhysObject(const PhysObject& object) :
m_matrix(object.m_matrix),
RigidBody3D::RigidBody3D(const RigidBody3D& object) :
m_geom(object.m_geom),
m_matrix(object.m_matrix),
m_forceAccumulator(Vector3f::Zero()),
m_torqueAccumulator(Vector3f::Zero()),
m_world(object.m_world),
@@ -52,9 +52,9 @@ namespace Nz
SetMass(object.m_mass);
}
PhysObject::PhysObject(PhysObject&& object) :
m_matrix(std::move(object.m_matrix)),
RigidBody3D::RigidBody3D(RigidBody3D&& object) :
m_geom(std::move(object.m_geom)),
m_matrix(std::move(object.m_matrix)),
m_forceAccumulator(std::move(object.m_forceAccumulator)),
m_torqueAccumulator(std::move(object.m_torqueAccumulator)),
m_body(object.m_body),
@@ -65,13 +65,13 @@ namespace Nz
object.m_body = nullptr;
}
PhysObject::~PhysObject()
RigidBody3D::~RigidBody3D()
{
if (m_body)
NewtonDestroyBody(m_body);
}
void PhysObject::AddForce(const Vector3f& force, CoordSys coordSys)
void RigidBody3D::AddForce(const Vector3f& force, CoordSys coordSys)
{
switch (coordSys)
{
@@ -88,7 +88,7 @@ namespace Nz
NewtonBodySetSleepState(m_body, 0);
}
void PhysObject::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys)
void RigidBody3D::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys)
{
switch (coordSys)
{
@@ -105,7 +105,7 @@ namespace Nz
NewtonBodySetSleepState(m_body, 0);
}
void PhysObject::AddTorque(const Vector3f& torque, CoordSys coordSys)
void RigidBody3D::AddTorque(const Vector3f& torque, CoordSys coordSys)
{
switch (coordSys)
{
@@ -122,12 +122,12 @@ namespace Nz
NewtonBodySetSleepState(m_body, 0);
}
void PhysObject::EnableAutoSleep(bool autoSleep)
void RigidBody3D::EnableAutoSleep(bool autoSleep)
{
NewtonBodySetAutoSleep(m_body, autoSleep);
}
Boxf PhysObject::GetAABB() const
Boxf RigidBody3D::GetAABB() const
{
Vector3f min, max;
NewtonBodyGetAABB(m_body, min, max);
@@ -135,7 +135,7 @@ namespace Nz
return Boxf(min, max);
}
Vector3f PhysObject::GetAngularVelocity() const
Vector3f RigidBody3D::GetAngularVelocity() const
{
Vector3f angularVelocity;
NewtonBodyGetOmega(m_body, angularVelocity);
@@ -143,27 +143,27 @@ namespace Nz
return angularVelocity;
}
const PhysGeomRef& PhysObject::GetGeom() const
const Collider3DRef& RigidBody3D::GetGeom() const
{
return m_geom;
}
float PhysObject::GetGravityFactor() const
float RigidBody3D::GetGravityFactor() const
{
return m_gravityFactor;
}
NewtonBody* PhysObject::GetHandle() const
NewtonBody* RigidBody3D::GetHandle() const
{
return m_body;
}
float PhysObject::GetMass() const
float RigidBody3D::GetMass() const
{
return m_mass;
}
Vector3f PhysObject::GetMassCenter(CoordSys coordSys) const
Vector3f RigidBody3D::GetMassCenter(CoordSys coordSys) const
{
Vector3f center;
NewtonBodyGetCentreOfMass(m_body, center);
@@ -181,22 +181,22 @@ namespace Nz
return center;
}
const Matrix4f& PhysObject::GetMatrix() const
const Matrix4f& RigidBody3D::GetMatrix() const
{
return m_matrix;
}
Vector3f PhysObject::GetPosition() const
Vector3f RigidBody3D::GetPosition() const
{
return m_matrix.GetTranslation();
}
Quaternionf PhysObject::GetRotation() const
Quaternionf RigidBody3D::GetRotation() const
{
return m_matrix.GetRotation();
}
Vector3f PhysObject::GetVelocity() const
Vector3f RigidBody3D::GetVelocity() const
{
Vector3f velocity;
NewtonBodyGetVelocity(m_body, velocity);
@@ -204,50 +204,52 @@ namespace Nz
return velocity;
}
bool PhysObject::IsAutoSleepEnabled() const
bool RigidBody3D::IsAutoSleepEnabled() const
{
return NewtonBodyGetAutoSleep(m_body) != 0;
}
bool PhysObject::IsMoveable() const
bool RigidBody3D::IsMoveable() const
{
return m_mass > 0.f;
}
bool PhysObject::IsSleeping() const
bool RigidBody3D::IsSleeping() const
{
return NewtonBodyGetSleepState(m_body) != 0;
}
void PhysObject::SetAngularVelocity(const Vector3f& angularVelocity)
void RigidBody3D::SetAngularVelocity(const Vector3f& angularVelocity)
{
NewtonBodySetOmega(m_body, angularVelocity);
}
void PhysObject::SetGeom(PhysGeomRef geom)
void RigidBody3D::SetGeom(Collider3DRef geom)
{
if (m_geom.Get() != geom)
{
if (geom)
m_geom = geom;
else
m_geom = NullGeom::New();
m_geom = NullCollider3D::New();
NewtonBodySetCollision(m_body, m_geom->GetHandle(m_world));
}
}
void PhysObject::SetGravityFactor(float gravityFactor)
void RigidBody3D::SetGravityFactor(float gravityFactor)
{
m_gravityFactor = gravityFactor;
}
void PhysObject::SetMass(float mass)
void RigidBody3D::SetMass(float mass)
{
if (m_mass > 0.f)
{
// If we already have a mass, we already have an inertial matrix as well, just rescale it
float Ix, Iy, Iz;
NewtonBodyGetMassMatrix(m_body, &m_mass, &Ix, &Iy, &Iz);
float scale = mass/m_mass;
NewtonBodySetMassMatrix(m_body, mass, Ix*scale, Iy*scale, Iz*scale);
}
@@ -265,41 +267,44 @@ namespace Nz
m_mass = mass;
}
void PhysObject::SetMassCenter(const Vector3f& center)
void RigidBody3D::SetMassCenter(const Vector3f& center)
{
if (m_mass > 0.f)
NewtonBodySetCentreOfMass(m_body, center);
}
void PhysObject::SetPosition(const Vector3f& position)
void RigidBody3D::SetPosition(const Vector3f& position)
{
m_matrix.SetTranslation(position);
UpdateBody();
}
void PhysObject::SetRotation(const Quaternionf& rotation)
void RigidBody3D::SetRotation(const Quaternionf& rotation)
{
m_matrix.SetRotation(rotation);
UpdateBody();
}
void PhysObject::SetVelocity(const Vector3f& velocity)
void RigidBody3D::SetVelocity(const Vector3f& velocity)
{
NewtonBodySetVelocity(m_body, velocity);
}
PhysObject& PhysObject::operator=(const PhysObject& object)
RigidBody3D& RigidBody3D::operator=(const RigidBody3D& object)
{
PhysObject physObj(object);
RigidBody3D physObj(object);
return operator=(std::move(physObj));
}
void PhysObject::UpdateBody()
void RigidBody3D::UpdateBody()
{
NewtonBodySetMatrix(m_body, m_matrix);
if (NumberEquals(m_mass, 0.f))
{
// Moving a static body in Newton does not update bodies at the target location
// http://newtondynamics.com/wiki/index.php5?title=Can_i_dynamicly_move_a_TriMesh%3F
Vector3f min, max;
NewtonBodyGetAABB(m_body, min, max);
@@ -312,11 +317,9 @@ namespace Nz
},
nullptr);
}
/*for (std::set<PhysObjectListener*>::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it)
(*it)->PhysObjectOnUpdate(this);*/
}
PhysObject& PhysObject::operator=(PhysObject&& object)
RigidBody3D& RigidBody3D::operator=(RigidBody3D&& object)
{
if (m_body)
NewtonDestroyBody(m_body);
@@ -335,36 +338,30 @@ namespace Nz
return *this;
}
void PhysObject::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex)
void RigidBody3D::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex)
{
NazaraUnused(timeStep);
NazaraUnused(threadIndex);
PhysObject* me = static_cast<PhysObject*>(NewtonBodyGetUserData(body));
RigidBody3D* me = static_cast<RigidBody3D*>(NewtonBodyGetUserData(body));
if (!NumberEquals(me->m_gravityFactor, 0.f))
me->m_forceAccumulator += me->m_world->GetGravity() * me->m_gravityFactor * me->m_mass;
/*for (std::set<PhysObjectListener*>::iterator it = me->m_listeners.begin(); it != me->m_listeners.end(); ++it)
(*it)->PhysObjectApplyForce(me);*/
NewtonBodySetForce(body, me->m_forceAccumulator);
NewtonBodySetTorque(body, me->m_torqueAccumulator);
me->m_torqueAccumulator.Set(0.f);
me->m_forceAccumulator.Set(0.f);
///TODO: Implanter la force gyroscopique?
///TODO: Implement gyroscopic force?
}
void PhysObject::TransformCallback(const NewtonBody* body, const float* matrix, int threadIndex)
void RigidBody3D::TransformCallback(const NewtonBody* body, const float* matrix, int threadIndex)
{
NazaraUnused(threadIndex);
PhysObject* me = static_cast<PhysObject*>(NewtonBodyGetUserData(body));
RigidBody3D* me = static_cast<RigidBody3D*>(NewtonBodyGetUserData(body));
me->m_matrix.Set(matrix);
/*for (std::set<PhysObjectListener*>::iterator it = me->m_listeners.begin(); it != me->m_listeners.end(); ++it)
(*it)->PhysObjectOnUpdate(me);*/
}
}
}

View File

@@ -11,7 +11,7 @@
namespace Nz
{
class ContextParameters;
struct ContextParameters;
class ContextImpl
{

View File

@@ -76,7 +76,7 @@ namespace Nz
code << "#define GLSL_VERSION " << glslVersion << "\n\n";
code << "#define EARLY_FRAGMENT_TEST " << ((glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) ? '1' : '0') << "\n\n";
code << "#define EARLY_FRAGMENT_TESTS " << ((glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) ? '1' : '0') << "\n\n";
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n';

View File

@@ -25,7 +25,7 @@ namespace Nz
return parser.Check();
}
bool Load(Animation* animation, Stream& stream, const AnimationParams& parameters)
bool Load(Animation* animation, Stream& stream, const AnimationParams& /*parameters*/)
{
///TODO: Utiliser les paramètres
MD5AnimParser parser(stream);

View File

@@ -304,7 +304,7 @@ namespace Nz
const Material& mat = pair.second;
Emit("newmtl ");
EmitLine(pair.first);
EmitLine(matName);
EmitLine();
Emit("Ka ");

View File

@@ -66,6 +66,8 @@ namespace Nz
bool SaveToStream(const Mesh& mesh, const String& format, Stream& stream, const MeshParams& parameters)
{
NazaraUnused(parameters);
if (!mesh.IsValid())
{
NazaraError("Invalid mesh");

View File

@@ -99,7 +99,7 @@ namespace Nz
void WriteToStream(void* userdata, void* data, int size)
{
Stream* stream = static_cast<Stream*>(userdata);
if (stream->Write(data, size) != size)
if (stream->Write(data, size) != static_cast<std::size_t>(size))
throw std::runtime_error("Failed to write to stream");
}
@@ -142,6 +142,8 @@ namespace Nz
bool SaveBMP(const Image& image, const ImageParams& parameters, Stream& stream)
{
NazaraUnused(parameters);
Image tempImage(image); //< We're using COW here to prevent Image copy unless required
int componentCount = ConvertToIntegerFormat(tempImage);
@@ -159,9 +161,11 @@ namespace Nz
return true;
}
bool SaveHDR(const Image& image, const ImageParams& parameters, Stream& stream)
{
NazaraUnused(parameters);
Image tempImage(image); //< We're using COW here to prevent Image copy unless required
int componentCount = ConvertToFloatFormat(tempImage);
@@ -182,6 +186,8 @@ namespace Nz
bool SavePNG(const Image& image, const ImageParams& parameters, Stream& stream)
{
NazaraUnused(parameters);
Image tempImage(image); //< We're using COW here to prevent Image copy unless required
int componentCount = ConvertToIntegerFormat(tempImage);
@@ -202,6 +208,8 @@ namespace Nz
bool SaveTGA(const Image& image, const ImageParams& parameters, Stream& stream)
{
NazaraUnused(parameters);
Image tempImage(image); //< We're using COW here to prevent Image copy unless required
int componentCount = ConvertToIntegerFormat(tempImage);

View File

@@ -11,10 +11,8 @@
namespace Nz
{
SoftwareBuffer::SoftwareBuffer(Buffer* parent, BufferType type) :
m_type(type)
SoftwareBuffer::SoftwareBuffer(Buffer* /*parent*/, BufferType type)
{
NazaraUnused(parent);
}
SoftwareBuffer::~SoftwareBuffer()
@@ -25,7 +23,7 @@ namespace Nz
{
NazaraUnused(usage);
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
// Protect the allocation to prevent a memory exception to escape the function
try
{
m_buffer = new UInt8[size];
@@ -46,20 +44,11 @@ namespace Nz
delete[] m_buffer;
}
bool SoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
bool SoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool /*forceDiscard*/)
{
NazaraUnused(forceDiscard);
#if NAZARA_UTILITY_SAFE
if (m_mapped)
{
NazaraError("Buffer already mapped");
return false;
}
#endif
NazaraAssert(!m_mapped, "Buffer is already mapped");
std::memcpy(&m_buffer[offset], data, size);
return true;
}
@@ -68,18 +57,9 @@ namespace Nz
return false;
}
void* SoftwareBuffer::Map(BufferAccess access, unsigned int offset, unsigned int size)
void* SoftwareBuffer::Map(BufferAccess /*access*/, unsigned int offset, unsigned int /*size*/)
{
NazaraUnused(access);
NazaraUnused(size);
#if NAZARA_UTILITY_SAFE
if (m_mapped)
{
NazaraError("Buffer already mapped");
return nullptr;
}
#endif
NazaraAssert(!m_mapped, "Buffer is already mapped");
m_mapped = true;
@@ -88,13 +68,7 @@ namespace Nz
bool SoftwareBuffer::Unmap()
{
#if NAZARA_UTILITY_SAFE
if (!m_mapped)
{
NazaraError("Buffer not mapped");
return true;
}
#endif
NazaraAssert(m_mapped, "Buffer is not mapped");
m_mapped = false;

View File

@@ -29,7 +29,6 @@ namespace Nz
bool Unmap();
private:
BufferType m_type;
UInt8* m_buffer;
bool m_mapped;
};

View File

@@ -768,19 +768,79 @@ namespace Nz
if (!keysyms)
{
NazaraError("Failed to get key symbols");
return XCB_NONE;
return XCB_NO_SYMBOL;
}
int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0;
const int altGrOffset = 4;
if (state & XCB_MOD_MASK_5)
col += altGrOffset;
xcb_keysym_t keysym = xcb_key_symbols_get_keysym(keysyms, keycode, col);
if (keysym == XCB_NO_SYMBOL)
keysym = xcb_key_symbols_get_keysym(keysyms, keycode, col ^ 0x1);
X11::XCBKeySymbolsFree(keysyms);
xcb_keysym_t k0, k1;
return keysym;
CallOnExit onExit([&](){
X11::XCBKeySymbolsFree(keysyms);
});
// Based on documentation in https://cgit.freedesktop.org/xcb/util-keysyms/tree/keysyms/keysyms.c
// Mode switch = ctlr and alt gr = XCB_MOD_MASK_5
// The first four elements of the list are split into two groups of KeySyms.
if (state & XCB_MOD_MASK_1)
{
k0 = xcb_key_symbols_get_keysym(keysyms, keycode, 2);
k1 = xcb_key_symbols_get_keysym(keysyms, keycode, 3);
}
if (state & XCB_MOD_MASK_5)
{
k0 = xcb_key_symbols_get_keysym(keysyms, keycode, 4);
k1 = xcb_key_symbols_get_keysym(keysyms, keycode, 5);
}
else
{
k0 = xcb_key_symbols_get_keysym(keysyms, keycode, 0);
k1 = xcb_key_symbols_get_keysym(keysyms, keycode, 1);
}
// If the second element of the group is NoSymbol, then the group should be treated as if the second element were the same as the first element.
if (k1 == XCB_NO_SYMBOL)
k1 = k0;
/* The numlock modifier is on and the second KeySym is a keypad KeySym
The numlock modifier is on and the second KeySym is a keypad KeySym. In
this case, if the Shift modifier is on, or if the Lock modifier is on
and is interpreted as ShiftLock, then the first KeySym is used,
otherwise the second KeySym is used.
*/
if ((state & XCB_MOD_MASK_2) && xcb_is_keypad_key(k1))
{
if ((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK && (state & XCB_MOD_MASK_SHIFT)))
return k0;
else
return k1;
}
/* The Shift and Lock modifiers are both off. In this case, the first
KeySym is used.*/
else if (!(state & XCB_MOD_MASK_SHIFT) && !(state & XCB_MOD_MASK_LOCK))
return k0;
/* The Shift modifier is off, and the Lock modifier is on and is
interpreted as CapsLock. In this case, the first KeySym is used, but
if that KeySym is lowercase alphabetic, then the corresponding
uppercase KeySym is used instead. */
else if (!(state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK && (state & XCB_MOD_MASK_SHIFT)))
return k0;
/* The Shift modifier is on, and the Lock modifier is on and is
interpreted as CapsLock. In this case, the second KeySym is used, but
if that KeySym is lowercase alphabetic, then the corresponding
uppercase KeySym is used instead.*/
else if ((state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK && (state & XCB_MOD_MASK_SHIFT)))
return k1;
/* The Shift modifier is on, or the Lock modifier is on and is
interpreted as ShiftLock, or both. In this case, the second KeySym is
used. */
else if ((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK && (state & XCB_MOD_MASK_SHIFT)))
return k1;
return XCB_NO_SYMBOL;
}
Keyboard::Key WindowImpl::ConvertVirtualKey(xcb_keysym_t symbol)
@@ -1013,6 +1073,64 @@ namespace Nz
xcb_flush(connection);
}
char32_t WindowImpl::GetRepresentation(xcb_keysym_t keysym) const
{
switch (keysym)
{
case XK_KP_Space:
return ' ';
case XK_BackSpace:
return '\b';
case XK_Tab:
case XK_KP_Tab:
return '\t';
case XK_Linefeed:
return '\n';
case XK_Return:
return '\r';
// Numpad
case XK_KP_Multiply:
return '*';
case XK_KP_Add:
return '+';
case XK_KP_Separator:
return ','; // In french, it's '.'
case XK_KP_Subtract:
return '-';
case XK_KP_Decimal:
return '.'; // In french, it's ','
case XK_KP_Divide:
return '/';
case XK_KP_0:
return '0';
case XK_KP_1:
return '1';
case XK_KP_2:
return '2';
case XK_KP_3:
return '3';
case XK_KP_4:
return '4';
case XK_KP_5:
return '5';
case XK_KP_6:
return '6';
case XK_KP_7:
return '7';
case XK_KP_8:
return '8';
case XK_KP_9:
return '9';
case XK_KP_Enter:
return '\r';
default:
if (xcb_is_modifier_key(keysym) == true)
return '\0';
else
return keysym;
}
}
void WindowImpl::ProcessEvent(xcb_generic_event_t* windowEvent)
{
if (!m_eventListener)
@@ -1127,7 +1245,7 @@ namespace Nz
event.key.system = keyPressEvent->state & XCB_MOD_MASK_4;
m_parent->PushEvent(event);
char32_t codePoint = static_cast<char32_t>(keysym);
char32_t codePoint = GetRepresentation(keysym);
// WTF if (std::isprint(codePoint, std::locale(""))) + handle combining ?
{

View File

@@ -89,6 +89,8 @@ namespace Nz
const char* ConvertWindowCursorToXName(WindowCursor cursor);
void CommonInitialize();
char32_t GetRepresentation(xcb_keysym_t keysym) const;
void ProcessEvent(xcb_generic_event_t* windowEvent);
void ResetVideoMode();