Merge remote-tracking branch 'refs/remotes/origin/master' into vulkan
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,9 @@ namespace Nz
|
||||
|
||||
bool Log::Initialize()
|
||||
{
|
||||
SetLogger(new FileLogger());
|
||||
if (s_logger == &s_stdLogger)
|
||||
SetLogger(new FileLogger());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Nz
|
||||
* \return Always returns true
|
||||
*/
|
||||
|
||||
bool StdLogger::IsStdReplicationEnabled()
|
||||
bool StdLogger::IsStdReplicationEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -282,7 +282,6 @@ namespace Nz
|
||||
{
|
||||
for (auto& pipelinePair : layer.opaqueModels)
|
||||
{
|
||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
|
||||
if (pipelineEntry.maxInstanceCount > 0)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -542,9 +542,7 @@ namespace Nz
|
||||
auto& overlayMap = matEntry.overlayMap;
|
||||
for (auto& overlayIt : overlayMap)
|
||||
{
|
||||
const Texture* overlay = overlayIt.first;
|
||||
auto& spriteChainVector = overlayIt.second.spriteChains;
|
||||
|
||||
spriteChainVector.clear();
|
||||
}
|
||||
|
||||
@@ -563,9 +561,7 @@ namespace Nz
|
||||
{
|
||||
for (auto& materialPair : pipelineEntry.materialMap)
|
||||
{
|
||||
const Material* material = materialPair.first;
|
||||
auto& matEntry = materialPair.second;
|
||||
|
||||
if (matEntry.enabled)
|
||||
{
|
||||
MeshInstanceContainer& meshInstances = matEntry.meshMap;
|
||||
@@ -573,7 +569,6 @@ namespace Nz
|
||||
for (auto& meshIt : meshInstances)
|
||||
{
|
||||
auto& meshEntry = meshIt.second;
|
||||
|
||||
meshEntry.instances.clear();
|
||||
}
|
||||
matEntry.enabled = false;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -593,7 +592,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();
|
||||
|
||||
@@ -149,22 +149,22 @@ namespace Nz
|
||||
lua_close(m_state);
|
||||
}
|
||||
|
||||
void LuaInstance::ArgCheck(bool condition, unsigned int argNum, const char* error)
|
||||
void LuaInstance::ArgCheck(bool condition, unsigned int argNum, const char* error) const
|
||||
{
|
||||
luaL_argcheck(m_state, condition, argNum, error);
|
||||
}
|
||||
|
||||
void LuaInstance::ArgCheck(bool condition, unsigned int argNum, const String& error)
|
||||
void LuaInstance::ArgCheck(bool condition, unsigned int argNum, const String& error) const
|
||||
{
|
||||
luaL_argcheck(m_state, condition, argNum, error.GetConstBuffer());
|
||||
}
|
||||
|
||||
int LuaInstance::ArgError(unsigned int argNum, const char* error)
|
||||
int LuaInstance::ArgError(unsigned int argNum, const char* error) const
|
||||
{
|
||||
return luaL_argerror(m_state, argNum, error);
|
||||
}
|
||||
|
||||
int LuaInstance::ArgError(unsigned int argNum, const String& error)
|
||||
int LuaInstance::ArgError(unsigned int argNum, const String& error) const
|
||||
{
|
||||
return luaL_argerror(m_state, argNum, error.GetConstBuffer());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
87
src/Nazara/Physics2D/Collider2D.cpp
Normal file
87
src/Nazara/Physics2D/Collider2D.cpp
Normal 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*>();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
60
src/Nazara/Physics2D/PhysWorld2D.cpp
Normal file
60
src/Nazara/Physics2D/PhysWorld2D.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/Nazara/Physics2D/Physics2D.cpp
Normal file
59
src/Nazara/Physics2D/Physics2D.cpp
Normal 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;
|
||||
}
|
||||
251
src/Nazara/Physics2D/RigidBody2D.cpp
Normal file
251
src/Nazara/Physics2D/RigidBody2D.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
445
src/Nazara/Physics3D/Collider3D.cpp
Normal file
445
src/Nazara/Physics3D/Collider3D.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
31
src/Nazara/Physics3D/Debug/NewOverload.cpp
Normal file
31
src/Nazara/Physics3D/Debug/NewOverload.cpp
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -304,7 +304,7 @@ namespace Nz
|
||||
const Material& mat = pair.second;
|
||||
|
||||
Emit("newmtl ");
|
||||
EmitLine(pair.first);
|
||||
EmitLine(matName);
|
||||
EmitLine();
|
||||
|
||||
Emit("Ka ");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Nz
|
||||
}
|
||||
|
||||
Image::Image(const Image& image) :
|
||||
RefCounted(),
|
||||
AbstractImage(image),
|
||||
Resource(),
|
||||
m_sharedImage(image.m_sharedImage)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace Nz
|
||||
bool Unmap();
|
||||
|
||||
private:
|
||||
BufferType m_type;
|
||||
UInt8* m_buffer;
|
||||
bool m_mapped;
|
||||
};
|
||||
|
||||
@@ -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 ?
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user