diff --git a/include/Nazara/Physics/Geom.hpp b/include/Nazara/Physics/Geom.hpp index d85077b9d..81319d713 100644 --- a/include/Nazara/Physics/Geom.hpp +++ b/include/Nazara/Physics/Geom.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// 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 @@ -18,6 +18,7 @@ #include #include #include +#include ///TODO: CollisionModifier ///TODO: HeightfieldGeom @@ -38,24 +39,23 @@ using NzPhysGeomRef = NzObjectRef; class NAZARA_API NzPhysGeom : public NzRefCounted, NzNonCopyable { public: - NzPhysGeom(NzPhysWorld* physWorld); + NzPhysGeom() = default; virtual ~NzPhysGeom(); - virtual NzBoxf ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const; - virtual NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity()) const; + NzBoxf ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const; + virtual NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const; virtual void ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const; virtual float ComputeVolume() const; - NewtonCollision* GetHandle() const; + NewtonCollision* GetHandle(NzPhysWorld* world) const; virtual nzGeomType GetType() const = 0; - NzPhysWorld* GetWorld() const; - - static NzPhysGeomRef Build(NzPhysWorld* physWorld, const NzPrimitiveList& list); + static NzPhysGeomRef Build(const NzPrimitiveList& list); protected: - NewtonCollision* m_collision; - NzPhysWorld* m_world; + virtual NewtonCollision* CreateHandle(NzPhysWorld* world) const = 0; + + mutable std::unordered_map m_handles; static NzPhysGeomLibrary::LibraryMap s_library; }; @@ -70,8 +70,11 @@ using NzBoxGeomRef = NzObjectRef; class NAZARA_API NzBoxGeom : public NzPhysGeom { public: - NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzBoxGeom(const NzVector3f& lengths, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzBoxGeom(const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + + NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const override; + float ComputeVolume() const override; NzVector3f GetLengths() const; nzGeomType GetType() const override; @@ -79,6 +82,9 @@ class NAZARA_API NzBoxGeom : public NzPhysGeom template static NzBoxGeomRef New(Args&&... args); private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + NzMatrix4f m_matrix; NzVector3f m_lengths; }; @@ -92,8 +98,8 @@ using NzCapsuleGeomRef = NzObjectRef; class NAZARA_API NzCapsuleGeom : public NzPhysGeom { public: - NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzCapsuleGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzCapsuleGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); float GetLength() const; float GetRadius() const; @@ -102,6 +108,9 @@ class NAZARA_API NzCapsuleGeom : public NzPhysGeom template static NzCapsuleGeomRef New(Args&&... args); private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + NzMatrix4f m_matrix; float m_length; float m_radius; }; @@ -116,7 +125,7 @@ using NzCompoundGeomRef = NzObjectRef; class NAZARA_API NzCompoundGeom : public NzPhysGeom { public: - NzCompoundGeom(NzPhysWorld* physWorld, NzPhysGeom** geoms, unsigned int geomCount); + NzCompoundGeom(NzPhysGeom** geoms, unsigned int geomCount); const std::vector& GetGeoms() const; nzGeomType GetType() const override; @@ -124,6 +133,8 @@ class NAZARA_API NzCompoundGeom : public NzPhysGeom template static NzCompoundGeomRef New(Args&&... args); private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + std::vector m_geoms; }; @@ -137,8 +148,8 @@ using NzConeGeomRef = NzObjectRef; class NAZARA_API NzConeGeom : public NzPhysGeom { public: - NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzConeGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzConeGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); float GetLength() const; float GetRadius() const; @@ -147,6 +158,9 @@ class NAZARA_API NzConeGeom : public NzPhysGeom template static NzConeGeomRef New(Args&&... args); private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + NzMatrix4f m_matrix; float m_length; float m_radius; }; @@ -161,12 +175,20 @@ using NzConvexHullGeomRef = NzObjectRef; class NAZARA_API NzConvexHullGeom : public NzPhysGeom { public: - NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride = sizeof(NzVector3f), float tolerance = 0.002f, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride = sizeof(NzVector3f), float tolerance = 0.002f, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); nzGeomType GetType() const override; template static NzConvexHullGeomRef New(Args&&... args); + + private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + std::vector m_vertices; + NzMatrix4f m_matrix; + float m_tolerance; + unsigned int m_vertexStride; }; class NzCylinderGeom; @@ -179,8 +201,8 @@ using NzCylinderGeomRef = NzObjectRef; class NAZARA_API NzCylinderGeom : public NzPhysGeom { public: - NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzCylinderGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzCylinderGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); float GetLength() const; float GetRadius() const; @@ -189,6 +211,9 @@ class NAZARA_API NzCylinderGeom : public NzPhysGeom template static NzCylinderGeomRef New(Args&&... args); private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + NzMatrix4f m_matrix; float m_length; float m_radius; }; @@ -203,11 +228,14 @@ using NzNullGeomRef = NzObjectRef; class NAZARA_API NzNullGeom : public NzPhysGeom { public: - NzNullGeom(NzPhysWorld* physWorld); + NzNullGeom(); nzGeomType GetType() const override; template static NzNullGeomRef New(Args&&... args); + + private: + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; }; class NzSphereGeom; @@ -220,16 +248,22 @@ using NzSphereGeomRef = NzObjectRef; class NAZARA_API NzSphereGeom : public NzPhysGeom { public: - NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); - NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); + NzSphereGeom(float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzSphereGeom(float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); - NzVector3f GetRadius() const; + NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const override; + float ComputeVolume() const override; + + float GetRadius() const; nzGeomType GetType() const override; template static NzSphereGeomRef New(Args&&... args); private: - NzVector3f m_radius; + NewtonCollision* CreateHandle(NzPhysWorld* world) const override; + + NzVector3f m_position; + float m_radius; }; #include diff --git a/src/Nazara/Physics/Geom.cpp b/src/Nazara/Physics/Geom.cpp index 681628a9a..0651921af 100644 --- a/src/Nazara/Physics/Geom.cpp +++ b/src/Nazara/Physics/Geom.cpp @@ -10,54 +10,59 @@ namespace { - NzPhysGeom* CreateGeomFromPrimitive(NzPhysWorld* physWorld, const NzPrimitive& primitive) + NzPhysGeomRef CreateGeomFromPrimitive(const NzPrimitive& primitive) { switch (primitive.type) { case nzPrimitiveType_Box: - return NzBoxGeom::New(physWorld, primitive.box.lengths, primitive.matrix); + return NzBoxGeom::New(primitive.box.lengths, primitive.matrix); case nzPrimitiveType_Cone: - return NzConeGeom::New(physWorld, primitive.cone.length, primitive.cone.radius, primitive.matrix); + return NzConeGeom::New(primitive.cone.length, primitive.cone.radius, primitive.matrix); case nzPrimitiveType_Plane: - return NzBoxGeom::New(physWorld, NzVector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix); + return NzBoxGeom::New(NzVector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix); ///TODO: PlaneGeom? case nzPrimitiveType_Sphere: - return NzSphereGeom::New(physWorld, primitive.sphere.size, primitive.matrix.GetTranslation()); + return NzSphereGeom::New(primitive.sphere.size, primitive.matrix.GetTranslation()); } NazaraError("Primitive type not handled (0x" + NzString::Number(primitive.type, 16) + ')'); - return nullptr; + return NzPhysGeomRef(); } } -NzPhysGeom::NzPhysGeom(NzPhysWorld* physWorld) : -m_world(physWorld) -{ -} - NzPhysGeom::~NzPhysGeom() { - NewtonDestroyCollision(m_collision); + for (auto& pair : m_handles) + NewtonDestroyCollision(pair.second); } NzBoxf NzPhysGeom::ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const { - NzVector3f min, max; - NewtonCollisionCalculateAABB(m_collision, NzMatrix4f::Transform(translation, rotation), min, max); - - // Et on applique le scale à la fin - return NzBoxf(scale*min, scale*max); + return ComputeAABB(NzMatrix4f::Transform(translation, rotation), scale); } -NzBoxf NzPhysGeom::ComputeAABB(const NzMatrix4f& offsetMatrix) const +NzBoxf NzPhysGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const { NzVector3f min, max; - NewtonCollisionCalculateAABB(m_collision, offsetMatrix, min, max); - return NzBoxf(min, max); + // Si nous n'avons aucune instance, nous en créons une temporaire + if (m_handles.empty()) + { + NzPhysWorld 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 NzBoxf(scale * min, scale * max); } void NzPhysGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const @@ -65,7 +70,19 @@ void NzPhysGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) float inertiaMatrix[3]; float origin[3]; - NewtonConvexCollisionCalculateInertialMatrix(m_collision, inertiaMatrix, origin); + // Si nous n'avons aucune instance, nous en créons une temporaire + if (m_handles.empty()) + { + NzPhysWorld 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); @@ -76,20 +93,35 @@ void NzPhysGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) float NzPhysGeom::ComputeVolume() const { - return NewtonConvexCollisionCalculateVolume(m_collision); + float volume; + + // Si nous n'avons aucune instance, nous en créons une temporaire + if (m_handles.empty()) + { + NzPhysWorld 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* NzPhysGeom::GetHandle() const +NewtonCollision* NzPhysGeom::GetHandle(NzPhysWorld* world) const { - return m_collision; + 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; } -NzPhysWorld* NzPhysGeom::GetWorld() const -{ - return m_world; -} - -NzPhysGeomRef NzPhysGeom::Build(NzPhysWorld* physWorld, const NzPrimitiveList& list) +NzPhysGeomRef NzPhysGeom::Build(const NzPrimitiveList& list) { unsigned int primitiveCount = list.GetSize(); @@ -106,30 +138,45 @@ NzPhysGeomRef NzPhysGeom::Build(NzPhysWorld* physWorld, const NzPrimitiveList& l std::vector geoms(primitiveCount); for (unsigned int i = 0; i < primitiveCount; ++i) - geoms[i] = CreateGeomFromPrimitive(physWorld, list.GetPrimitive(i)); + geoms[i] = CreateGeomFromPrimitive(list.GetPrimitive(i)); - return NzCompoundGeom::New(physWorld, &geoms[0], primitiveCount); + return NzCompoundGeom::New(&geoms[0], primitiveCount); } else - return CreateGeomFromPrimitive(physWorld, list.GetPrimitive(0)); + return CreateGeomFromPrimitive(list.GetPrimitive(0)); } NzPhysGeomLibrary::LibraryMap NzPhysGeom::s_library; /********************************** BoxGeom **********************************/ -NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld), +NzBoxGeom::NzBoxGeom(const NzVector3f& lengths, const NzMatrix4f& transformMatrix) : +m_matrix(transformMatrix), m_lengths(lengths) { - m_collision = NewtonCreateBox(physWorld->GetHandle(), lengths.x, lengths.y, lengths.z, 0, transformMatrix); } -NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzBoxGeom(physWorld, lengths, NzMatrix4f::Transform(translation, rotation)) +NzBoxGeom::NzBoxGeom(const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzBoxGeom(lengths, NzMatrix4f::Transform(translation, rotation)) { } +NzBoxf NzBoxGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const +{ + NzVector3f halfLengths(m_lengths * 0.5f); + + NzBoxf 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 NzBoxGeom::ComputeVolume() const +{ + return m_lengths.x * m_lengths.y * m_lengths.z; +} + NzVector3f NzBoxGeom::GetLengths() const { return m_lengths; @@ -140,18 +187,22 @@ nzGeomType NzBoxGeom::GetType() const return nzGeomType_Box; } +NewtonCollision* NzBoxGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateBox(world->GetHandle(), m_lengths.x, m_lengths.y, m_lengths.z, 0, m_matrix); +} + /******************************** CapsuleGeom ********************************/ -NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld), +NzCapsuleGeom::NzCapsuleGeom(float length, float radius, const NzMatrix4f& transformMatrix) : +m_matrix(transformMatrix), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCapsule(physWorld->GetHandle(), radius, length, 0, transformMatrix); } -NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzCapsuleGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation)) +NzCapsuleGeom::NzCapsuleGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzCapsuleGeom(length, radius, NzMatrix4f::Transform(translation, rotation)) { } @@ -170,30 +221,18 @@ nzGeomType NzCapsuleGeom::GetType() const return nzGeomType_Capsule; } +NewtonCollision* NzCapsuleGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateCapsule(world->GetHandle(), m_radius, m_length, 0, m_matrix); +} + /******************************* CompoundGeom ********************************/ -NzCompoundGeom::NzCompoundGeom(NzPhysWorld* physWorld, NzPhysGeom** geoms, unsigned int geomCount) : -NzPhysGeom(physWorld) +NzCompoundGeom::NzCompoundGeom(NzPhysGeom** geoms, unsigned int geomCount) { - m_collision = NewtonCreateCompoundCollision(physWorld->GetHandle(), 0); - NewtonCompoundCollisionBeginAddRemove(m_collision); - m_geoms.reserve(geomCount); for (unsigned int i = 0; i < geomCount; ++i) - { - if (geoms[i]->GetType() == nzGeomType_Compound) - { - NzCompoundGeom* compoundGeom = static_cast(geoms[i]); - for (const NzPhysGeomRef& geom : compoundGeom->GetGeoms()) - NewtonCompoundCollisionAddSubCollision(m_collision, geom->GetHandle()); - } - else - NewtonCompoundCollisionAddSubCollision(m_collision, geoms[i]->GetHandle()); - m_geoms.emplace_back(geoms[i]); - } - - NewtonCompoundCollisionEndAddRemove(m_collision); } const std::vector& NzCompoundGeom::GetGeoms() const @@ -206,18 +245,38 @@ nzGeomType NzCompoundGeom::GetType() const return nzGeomType_Compound; } +NewtonCollision* NzCompoundGeom::CreateHandle(NzPhysWorld* world) const +{ + NewtonCollision* compoundCollision = NewtonCreateCompoundCollision(world->GetHandle(), 0); + + NewtonCompoundCollisionBeginAddRemove(compoundCollision); + for (const NzPhysGeomRef& geom : m_geoms) + { + if (geom->GetType() == nzGeomType_Compound) + { + NzCompoundGeom* compoundGeom = static_cast(geom.Get()); + for (const NzPhysGeomRef& piece : compoundGeom->GetGeoms()) + NewtonCompoundCollisionAddSubCollision(compoundCollision, piece->GetHandle(world)); + } + else + NewtonCompoundCollisionAddSubCollision(compoundCollision, geom->GetHandle(world)); + } + NewtonCompoundCollisionEndAddRemove(compoundCollision); + + return compoundCollision; +} + /********************************* ConeGeom **********************************/ -NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld), +NzConeGeom::NzConeGeom(float length, float radius, const NzMatrix4f& transformMatrix) : +m_matrix(transformMatrix), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCone(physWorld->GetHandle(), radius, length, 0, transformMatrix); } -NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzConeGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation)) +NzConeGeom::NzConeGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzConeGeom(length, radius, NzMatrix4f::Transform(translation, rotation)) { } @@ -236,16 +295,32 @@ nzGeomType NzConeGeom::GetType() const return nzGeomType_Cone; } -/****************************** ConvexHullGeom *******************************/ - -NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld) +NewtonCollision* NzConeGeom::CreateHandle(NzPhysWorld* world) const { - m_collision = NewtonCreateConvexHull(physWorld->GetHandle(), vertexCount, reinterpret_cast(vertices), stride, tolerance, 0, transformMatrix); + return NewtonCreateCone(world->GetHandle(), m_radius, m_length, 0, m_matrix); } -NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzConvexHullGeom(physWorld, vertices, vertexCount, stride, tolerance, NzMatrix4f::Transform(translation, rotation)) +/****************************** ConvexHullGeom *******************************/ + +NzConvexHullGeom::NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzMatrix4f& transformMatrix) : +m_matrix(transformMatrix), +m_tolerance(tolerance), +m_vertexStride(stride) +{ + const nzUInt8* ptr = static_cast(vertices); + + m_vertices.resize(vertexCount); + if (stride != sizeof(NzVector3f)) + { + for (unsigned int i = 0; i < vertexCount; ++i) + m_vertices[i] = *reinterpret_cast(ptr + stride*i); + } + else // Fast path + std::memcpy(m_vertices.data(), vertices, vertexCount*sizeof(NzVector3f)); +} + +NzConvexHullGeom::NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzConvexHullGeom(vertices, vertexCount, stride, tolerance, NzMatrix4f::Transform(translation, rotation)) { } @@ -254,18 +329,22 @@ nzGeomType NzConvexHullGeom::GetType() const return nzGeomType_Compound; } +NewtonCollision* NzConvexHullGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateConvexHull(world->GetHandle(), m_vertices.size(), reinterpret_cast(m_vertices.data()), sizeof(NzVector3f), m_tolerance, 0, m_matrix); +} + /******************************* CylinderGeom ********************************/ -NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld), +NzCylinderGeom::NzCylinderGeom(float length, float radius, const NzMatrix4f& transformMatrix) : +m_matrix(transformMatrix), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCylinder(physWorld->GetHandle(), radius, length, 0, transformMatrix); } -NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzCylinderGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation)) +NzCylinderGeom::NzCylinderGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzCylinderGeom(length, radius, NzMatrix4f::Transform(translation, rotation)) { } @@ -284,12 +363,15 @@ nzGeomType NzCylinderGeom::GetType() const return nzGeomType_Cylinder; } +NewtonCollision* NzCylinderGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateCylinder(world->GetHandle(), m_radius, m_length, 0, m_matrix); +} + /********************************* NullGeom **********************************/ -NzNullGeom::NzNullGeom(NzPhysWorld* physWorld) : -NzPhysGeom(physWorld) +NzNullGeom::NzNullGeom() { - m_collision = NewtonCreateNull(physWorld->GetHandle()); } nzGeomType NzNullGeom::GetType() const @@ -297,21 +379,39 @@ nzGeomType NzNullGeom::GetType() const return nzGeomType_Null; } +NewtonCollision* NzNullGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateNull(world->GetHandle()); +} + /******************************** SphereGeom *********************************/ -NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix) : -NzPhysGeom(physWorld), +NzSphereGeom::NzSphereGeom(float radius, const NzMatrix4f& transformMatrix) : +NzSphereGeom(radius, transformMatrix.GetTranslation()) +{ +} + +NzSphereGeom::NzSphereGeom(float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +m_position(translation), m_radius(radius) { - m_collision = NewtonCreateSphere(physWorld->GetHandle(), radius, 0, transformMatrix); + NazaraUnused(rotation); } -NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : -NzSphereGeom(physWorld, radius, NzMatrix4f::Transform(translation, rotation)) +NzBoxf NzSphereGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const { + NzVector3f size(m_radius * scale); + NzVector3f position(offsetMatrix.GetTranslation()); + + return NzBoxf(position - size, position + size); } -NzVector3f NzSphereGeom::GetRadius() const +float NzSphereGeom::ComputeVolume() const +{ + return M_PI * m_radius * m_radius * m_radius / 3.f; +} + +float NzSphereGeom::GetRadius() const { return m_radius; } @@ -320,3 +420,8 @@ nzGeomType NzSphereGeom::GetType() const { return nzGeomType_Sphere; } + +NewtonCollision* NzSphereGeom::CreateHandle(NzPhysWorld* world) const +{ + return NewtonCreateSphere(world->GetHandle(), m_radius, 0, NzMatrix4f::Translate(m_position)); +}