diff --git a/include/Nazara/Physics/Geom.hpp b/include/Nazara/Physics/Geom.hpp index cff4d13e7..1df340848 100644 --- a/include/Nazara/Physics/Geom.hpp +++ b/include/Nazara/Physics/Geom.hpp @@ -8,14 +8,16 @@ #define NAZARA_GEOM_HPP #include +#include #include -#include +#include #include #include #include ///TODO: CollisionModifier ///TODO: HeightfieldGeom +///TODO: PlaneGeom ? ///TODO: SceneGeom ///TODO: TreeGeom @@ -28,8 +30,8 @@ class NAZARA_API NzBaseGeom : NzNonCopyable NzBaseGeom(NzPhysWorld* physWorld); virtual ~NzBaseGeom(); - virtual NzCubef ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const; - virtual NzCubef ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity()) const; + virtual NzBoxf ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const; + virtual NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity()) const; virtual void ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const; virtual float ComputeVolume() const; @@ -38,6 +40,8 @@ class NAZARA_API NzBaseGeom : NzNonCopyable NzPhysWorld* GetWorld() const; + static NzBaseGeom* Build(NzPhysWorld* physWorld, const NzPrimitiveList& list); + protected: NewtonCollision* m_collision; NzPhysWorld* m_world; @@ -46,7 +50,8 @@ class NAZARA_API NzBaseGeom : NzNonCopyable class NAZARA_API NzBoxGeom : public NzBaseGeom { public: - NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation = NzVector3f::Zero(), const NzQuaternionf& rotation = NzQuaternionf::Identity()); + 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()); NzVector3f GetLengths() const; nzGeomType GetType() const override; @@ -58,7 +63,8 @@ class NAZARA_API NzBoxGeom : public NzBaseGeom class NAZARA_API NzCapsuleGeom : public NzBaseGeom { public: - NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation = NzVector3f::Zero(), const NzQuaternionf& rotation = NzQuaternionf::Identity()); + 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()); float GetLength() const; float GetRadius() const; @@ -72,7 +78,7 @@ class NAZARA_API NzCapsuleGeom : public NzBaseGeom class NAZARA_API NzCompoundGeom : public NzBaseGeom { public: - NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom* geoms, unsigned int geomCount); + NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom** geoms, unsigned int geomCount); nzGeomType GetType() const override; }; @@ -80,7 +86,8 @@ class NAZARA_API NzCompoundGeom : public NzBaseGeom class NAZARA_API NzConeGeom : public NzBaseGeom { public: - NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation = NzVector3f::Zero(), const NzQuaternionf& rotation = NzQuaternionf::Identity()); + 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()); float GetLength() const; float GetRadius() const; @@ -94,7 +101,8 @@ class NAZARA_API NzConeGeom : public NzBaseGeom class NAZARA_API NzConvexHullGeom : public NzBaseGeom { public: - NzConvexHullGeom(NzPhysWorld* physWorld, const NzVector3f* vertices, unsigned int vertexCount, unsigned int stride = sizeof(NzVector3f), float tolerance = 0.2f, const NzVector3f& translation = NzVector3f::Zero(), const NzQuaternionf& rotation = NzQuaternionf::Identity()); + 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()); nzGeomType GetType() const override; }; @@ -102,7 +110,8 @@ class NAZARA_API NzConvexHullGeom : public NzBaseGeom class NAZARA_API NzCylinderGeom : public NzBaseGeom { public: - NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation = NzVector3f::Zero(), const NzQuaternionf& rotation = NzQuaternionf::Identity()); + 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()); float GetLength() const; float GetRadius() const; @@ -124,8 +133,8 @@ class NAZARA_API NzNullGeom : public NzBaseGeom class NAZARA_API NzSphereGeom : public NzBaseGeom { public: - NzSphereGeom(NzPhysWorld* physWorld, const NzVector3f& radius, const NzVector3f& translation = NzVector3f::Zero()); - NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation = NzVector3f::Zero()); + NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity()); + NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity()); NzVector3f GetRadius() const; nzGeomType GetType() const override; diff --git a/include/Nazara/Physics/PhysObject.hpp b/include/Nazara/Physics/PhysObject.hpp index ced439967..bf6d233c4 100644 --- a/include/Nazara/Physics/PhysObject.hpp +++ b/include/Nazara/Physics/PhysObject.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013 Jérôme Leclercq +// Copyright (C) 2013 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 @@ -8,6 +8,7 @@ #define NAZARA_PHYSOBJECT_HPP #include +#include #include #include #include @@ -24,24 +25,40 @@ class NAZARA_API NzPhysObject : NzNonCopyable NzPhysObject(NzPhysWorld* world, const NzBaseGeom* geom, const NzMatrix4f& mat = NzMatrix4f::Identity()); ~NzPhysObject(); + void AddForce(const NzVector3f& force, nzCoordSys coordSys = nzCoordSys_Global); + void AddForce(const NzVector3f& force, const NzVector3f& point, nzCoordSys coordSys = nzCoordSys_Global); + void AddTorque(const NzVector3f& torque, nzCoordSys coordSys = nzCoordSys_Global); + + void EnableAutoSleep(bool autoSleep); + + NzVector3f GetAngularVelocity() const; float GetGravityFactor() const; + NewtonBody* GetHandle() const; float GetMass() const; - NzVector3f GetMassCenter() const; + NzVector3f GetMassCenter(nzCoordSys coordSys = nzCoordSys_Local) const; + const NzMatrix4f& GetMatrix() const; NzVector3f GetPosition() const; NzQuaternionf GetRotation() const; NzVector3f GetVelocity() const; + bool IsAutoSleepEnabled() const; bool IsMoveable() const; + bool IsSleeping() const; + void SetGravityFactor(float gravityFactor); void SetMass(float mass); - void SetMassCenter(NzVector3f center); + void SetMassCenter(const NzVector3f& center); + void SetPosition(const NzVector3f& position); + void SetRotation(const NzQuaternionf& rotation); private: + void UpdateBody(); static void ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex); static void TransformCallback(const NewtonBody* body, const float* matrix, int threadIndex); NzMatrix4f m_matrix; NzVector3f m_forceAccumulator; + NzVector3f m_torqueAccumulator; NewtonBody* m_body; const NzBaseGeom* m_geom; NzPhysWorld* m_world; diff --git a/include/Nazara/Physics/PhysWorld.hpp b/include/Nazara/Physics/PhysWorld.hpp index 6605fb140..205e95c8b 100644 --- a/include/Nazara/Physics/PhysWorld.hpp +++ b/include/Nazara/Physics/PhysWorld.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013 Jérôme Leclercq +// Copyright (C) 2013 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 @@ -22,18 +22,19 @@ class NAZARA_API NzPhysWorld : NzNonCopyable NzVector3f GetGravity() const; NewtonWorld* GetHandle() const; - unsigned int GetMemoryUsed() const; + float GetStepSize() const; void SetGravity(const NzVector3f& gravity); - void SetSize(const NzBoxf& box); - void SetSize(const NzVector3f& min, const NzVector3f& max); void SetSolverModel(unsigned int model); + void SetStepSize(float stepSize); - void Update(float timestep); + void Step(float timestep); private: NzVector3f m_gravity; NewtonWorld* m_world; + float m_stepSize; + float m_timestepAccumulator; }; #endif // NAZARA_PHYSWORLD_HPP diff --git a/src/Nazara/Physics/Geom.cpp b/src/Nazara/Physics/Geom.cpp index 71aa0bda6..bc7e88fdd 100644 --- a/src/Nazara/Physics/Geom.cpp +++ b/src/Nazara/Physics/Geom.cpp @@ -8,6 +8,28 @@ #include #include +namespace +{ + NzBaseGeom* CreateGeomFromPrimitive(NzPhysWorld* physWorld, const NzPrimitive& primitive) + { + switch (primitive.type) + { + case nzPrimitiveType_Box: + return new NzBoxGeom(physWorld, primitive.box.lengths, primitive.matrix); + + case nzPrimitiveType_Plane: + return new NzBoxGeom(physWorld, NzVector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix); + ///TODO: PlaneGeom? + + case nzPrimitiveType_Sphere: + return new NzSphereGeom(physWorld, primitive.sphere.size, primitive.matrix.GetTranslation()); + } + + NazaraError("Primitive type not handled (0x" + NzString::Number(primitive.type, 16) + ')'); + return nullptr; + } +} + NzBaseGeom::NzBaseGeom(NzPhysWorld* physWorld) : m_world(physWorld) { @@ -15,24 +37,24 @@ m_world(physWorld) NzBaseGeom::~NzBaseGeom() { - NewtonReleaseCollision(m_world->GetHandle(), m_collision); + NewtonDestroyCollision(m_collision); } -NzCubef NzBaseGeom::ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const +NzBoxf NzBaseGeom::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 NzCubef(scale*min, scale*max); + return NzBoxf(scale*min, scale*max); } -NzCubef NzBaseGeom::ComputeAABB(const NzMatrix4f& offsetMatrix) const +NzBoxf NzBaseGeom::ComputeAABB(const NzMatrix4f& offsetMatrix) const { NzVector3f min, max; NewtonCollisionCalculateAABB(m_collision, offsetMatrix, min, max); - return NzCubef(min, max); + return NzBoxf(min, max); } void NzBaseGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const @@ -64,13 +86,43 @@ NzPhysWorld* NzBaseGeom::GetWorld() const return m_world; } +NzBaseGeom* NzBaseGeom::Build(NzPhysWorld* physWorld, const NzPrimitiveList& list) +{ + unsigned int primitiveCount = list.GetSize(); + + #if NAZARA_PHYSICS_SAFE + if (primitiveCount == 0) + { + NazaraError("PrimitiveList must have at least one primitive"); + return nullptr; + } + #endif + + if (primitiveCount > 1) + { + std::vector geoms(primitiveCount); + + for (unsigned int i = 0; i < primitiveCount; ++i) + geoms[i] = CreateGeomFromPrimitive(physWorld, list.GetPrimitive(i)); + + return new NzCompoundGeom(physWorld, &geoms[0], primitiveCount); + } + else + return CreateGeomFromPrimitive(physWorld, list.GetPrimitive(0)); +} + /********************************** BoxGeom **********************************/ -NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld), m_lengths(lengths) { - m_collision = NewtonCreateBox(physWorld->GetHandle(), lengths.x, lengths.y, lengths.z, 0, NzMatrix4f::Transform(translation, rotation)); + 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)) +{ } NzVector3f NzBoxGeom::GetLengths() const @@ -85,12 +137,17 @@ nzGeomType NzBoxGeom::GetType() const /******************************** CapsuleGeom ********************************/ -NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCapsule(physWorld->GetHandle(), radius, length, 0, NzMatrix4f::Transform(translation, rotation)); + 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)) +{ } float NzCapsuleGeom::GetLength() const @@ -110,28 +167,21 @@ nzGeomType NzCapsuleGeom::GetType() const /******************************* CompoundGeom ********************************/ -NzCompoundGeom::NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom* geoms, unsigned int geomCount) : +NzCompoundGeom::NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom** geoms, unsigned int geomCount) : NzBaseGeom(physWorld) { - std::vector collisions; - collisions.reserve(geomCount); + m_collision = NewtonCreateCompoundCollision(physWorld->GetHandle(), 0); + NewtonCompoundCollisionBeginAddRemove(m_collision); for (unsigned int i = 0; i < geomCount; ++i) { - if (geoms[i].GetType() == nzGeomType_Compound) - { - NewtonCollisionInfoRecord info; - NewtonCollisionGetInfo(geoms[i].GetHandle(), &info); - - unsigned int count = info.m_compoundCollision.m_chidrenCount; - for (unsigned int j = 0; j < count; ++j) - collisions.push_back(info.m_compoundCollision.m_chidren[j]); - } + if (geoms[i]->GetType() == nzGeomType_Compound) + NazaraError("Cannot add compound geoms to other compound geoms"); else - collisions.push_back(geoms[i].GetHandle()); + NewtonCompoundCollisionAddSubCollision(m_collision, geoms[i]->GetHandle()); } - m_collision = NewtonCreateCompoundCollision(physWorld->GetHandle(), collisions.size(), &collisions[0], 0); + NewtonCompoundCollisionEndAddRemove(m_collision); } nzGeomType NzCompoundGeom::GetType() const @@ -141,12 +191,17 @@ nzGeomType NzCompoundGeom::GetType() const /********************************* ConeGeom **********************************/ -NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCone(physWorld->GetHandle(), radius, length, 0, NzMatrix4f::Transform(translation, rotation)); + 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)) +{ } float NzConeGeom::GetLength() const @@ -166,10 +221,15 @@ nzGeomType NzConeGeom::GetType() const /****************************** ConvexHullGeom *******************************/ -NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const NzVector3f* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld) { - m_collision = NewtonCreateConvexHull(physWorld->GetHandle(), vertexCount, reinterpret_cast(vertices), stride, tolerance, 0, NzMatrix4f::Transform(translation, rotation)); + m_collision = NewtonCreateConvexHull(physWorld->GetHandle(), vertexCount, reinterpret_cast(vertices), stride, tolerance, 0, transformMatrix); +} + +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)) +{ } nzGeomType NzConvexHullGeom::GetType() const @@ -179,12 +239,17 @@ nzGeomType NzConvexHullGeom::GetType() const /******************************* CylinderGeom ********************************/ -NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld), m_length(length), m_radius(radius) { - m_collision = NewtonCreateCylinder(physWorld->GetHandle(), radius, length, 0, NzMatrix4f::Transform(translation, rotation)); + 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)) +{ } float NzCylinderGeom::GetLength() const @@ -217,15 +282,15 @@ nzGeomType NzNullGeom::GetType() const /******************************** SphereGeom *********************************/ -NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, const NzVector3f& radius, const NzVector3f& translation) : +NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix) : NzBaseGeom(physWorld), m_radius(radius) { - m_collision = NewtonCreateSphere(physWorld->GetHandle(), radius.x, radius.y, radius.z, 0, NzMatrix4f::Translate(translation)); + m_collision = NewtonCreateSphere(physWorld->GetHandle(), radius, 0, transformMatrix); } -NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation) : -NzSphereGeom(physWorld, NzVector3f(radius), translation) +NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) : +NzSphereGeom(physWorld, radius, NzMatrix4f::Transform(translation, rotation)) { } diff --git a/src/Nazara/Physics/PhysObject.cpp b/src/Nazara/Physics/PhysObject.cpp index aab4ed368..a0af6578c 100644 --- a/src/Nazara/Physics/PhysObject.cpp +++ b/src/Nazara/Physics/PhysObject.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013 Jérôme Leclercq +// Copyright (C) 2013 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 @@ -12,6 +12,7 @@ NzPhysObject::NzPhysObject(NzPhysWorld* world, const NzMatrix4f& mat) : m_matrix(mat), m_forceAccumulator(NzVector3f::Zero()), +m_torqueAccumulator(NzVector3f::Zero()), m_world(world), m_ownsGeom(true), m_gravityFactor(1.f), @@ -23,13 +24,14 @@ m_mass(0.f) #endif m_geom = new NzNullGeom(world); - m_body = NewtonCreateBody(world->GetHandle(), m_geom->GetHandle(), mat); + m_body = NewtonCreateDynamicBody(world->GetHandle(), m_geom->GetHandle(), mat); NewtonBodySetUserData(m_body, this); } NzPhysObject::NzPhysObject(NzPhysWorld* world, const NzBaseGeom* geom, const NzMatrix4f& mat) : m_matrix(mat), m_forceAccumulator(NzVector3f::Zero()), +m_torqueAccumulator(NzVector3f::Zero()), m_geom(geom), m_world(world), m_ownsGeom(false), @@ -41,7 +43,7 @@ m_mass(0.f) NazaraError("Invalid physics world"); ///TODO: Unexcepted #endif - m_body = NewtonCreateBody(world->GetHandle(), geom->GetHandle(), mat); + m_body = NewtonCreateDynamicBody(world->GetHandle(), geom->GetHandle(), mat); NewtonBodySetUserData(m_body, this); } @@ -53,24 +55,109 @@ NzPhysObject::~NzPhysObject() delete m_geom; } +void NzPhysObject::AddForce(const NzVector3f& force, nzCoordSys coordSys) +{ + switch (coordSys) + { + case nzCoordSys_Global: + m_forceAccumulator += force; + break; + + case nzCoordSys_Local: + m_forceAccumulator += GetRotation()*force; + break; + } + + // On réveille le corps pour que le callback soit appelé et que les forces soient appliquées + NewtonBodySetSleepState(m_body, 0); +} + +void NzPhysObject::AddForce(const NzVector3f& force, const NzVector3f& point, nzCoordSys coordSys) +{ + switch (coordSys) + { + case nzCoordSys_Global: + m_forceAccumulator += force; + m_torqueAccumulator += NzVector3f::CrossProduct(point - GetMassCenter(nzCoordSys_Global), force); + break; + + case nzCoordSys_Local: + AddForce(m_matrix.Transform(force, 0.f), m_matrix.Transform(point)); + return; + } + + // On réveille le corps pour que le callback soit appelé et que les forces soient appliquées + NewtonBodySetSleepState(m_body, 0); +} + +void NzPhysObject::AddTorque(const NzVector3f& torque, nzCoordSys coordSys) +{ + switch (coordSys) + { + case nzCoordSys_Global: + m_torqueAccumulator += torque; + break; + + case nzCoordSys_Local: + m_torqueAccumulator += m_matrix.Transform(torque, 0.f); + break; + } + + // On réveille le corps pour que le callback soit appelé et que les forces soient appliquées + NewtonBodySetSleepState(m_body, 0); +} + +void NzPhysObject::EnableAutoSleep(bool autoSleep) +{ + NewtonBodySetAutoSleep(m_body, autoSleep); +} + +NzVector3f NzPhysObject::GetAngularVelocity() const +{ + NzVector3f angularVelocity; + NewtonBodyGetOmega(m_body, angularVelocity); + + return angularVelocity; +} + float NzPhysObject::GetGravityFactor() const { return m_gravityFactor; } +NewtonBody* NzPhysObject::GetHandle() const +{ + return m_body; +} + float NzPhysObject::GetMass() const { return m_mass; } -NzVector3f NzPhysObject::GetMassCenter() const +NzVector3f NzPhysObject::GetMassCenter(nzCoordSys coordSys) const { NzVector3f center; NewtonBodyGetCentreOfMass(m_body, center); + switch (coordSys) + { + case nzCoordSys_Global: + center = m_matrix.Transform(center); + break; + + case nzCoordSys_Local: + break; // Aucune opération à effectuer sur le centre de rotation + } + return center; } +const NzMatrix4f& NzPhysObject::GetMatrix() const +{ + return m_matrix; +} + NzVector3f NzPhysObject::GetPosition() const { return m_matrix.GetTranslation(); @@ -89,11 +176,26 @@ NzVector3f NzPhysObject::GetVelocity() const return velocity; } +bool NzPhysObject::IsAutoSleepEnabled() const +{ + return NewtonBodyGetAutoSleep(m_body) != 0; +} + bool NzPhysObject::IsMoveable() const { return m_mass > 0.f; } +bool NzPhysObject::IsSleeping() const +{ + return NewtonBodyGetSleepState(m_body) != 0; +} + +void NzPhysObject::SetGravityFactor(float gravityFactor) +{ + m_gravityFactor = gravityFactor; +} + void NzPhysObject::SetMass(float mass) { if (m_mass > 0.f) @@ -117,12 +219,31 @@ void NzPhysObject::SetMass(float mass) m_mass = mass; } -void NzPhysObject::SetMassCenter(NzVector3f center) +void NzPhysObject::SetMassCenter(const NzVector3f& center) { if (m_mass > 0.f) NewtonBodySetCentreOfMass(m_body, center); } +void NzPhysObject::SetPosition(const NzVector3f& position) +{ + m_matrix.SetTranslation(position); + UpdateBody(); +} + +void NzPhysObject::SetRotation(const NzQuaternionf& rotation) +{ + m_matrix.SetRotation(rotation); + UpdateBody(); +} + +void NzPhysObject::UpdateBody() +{ + NewtonBodySetMatrix(m_body, m_matrix); + /*for (std::set::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it) + (*it)->PhysObjectOnUpdate(this);*/ +} + void NzPhysObject::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex) { NazaraUnused(timeStep); @@ -137,10 +258,10 @@ void NzPhysObject::ForceAndTorqueCallback(const NewtonBody* body, float timeStep (*it)->PhysObjectApplyForce(me);*/ NewtonBodySetForce(body, me->m_forceAccumulator); - me->m_forceAccumulator.Set(0.f); + NewtonBodySetTorque(body, me->m_torqueAccumulator); - /*NewtonBodyAddTorque(body, &me->m_torqueAccumulator.x); - me->m_torqueAccumulator = 0.f;*/ + me->m_torqueAccumulator.Set(0.f); + me->m_forceAccumulator.Set(0.f); ///TODO: Implanter la force gyroscopique? } diff --git a/src/Nazara/Physics/PhysWorld.cpp b/src/Nazara/Physics/PhysWorld.cpp index fbf9b9efe..9f2ad1a90 100644 --- a/src/Nazara/Physics/PhysWorld.cpp +++ b/src/Nazara/Physics/PhysWorld.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013 Jérôme Leclercq +// Copyright (C) 2013 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 @@ -6,7 +6,10 @@ #include #include -NzPhysWorld::NzPhysWorld() +NzPhysWorld::NzPhysWorld() : +m_gravity(NzVector3f::Zero()), +m_stepSize(0.005f), +m_timestepAccumulator(0.f) { m_world = NewtonCreate(); NewtonWorldSetUserData(m_world, this); @@ -27,27 +30,33 @@ NewtonWorld* NzPhysWorld::GetHandle() const return m_world; } +float NzPhysWorld::GetStepSize() const +{ + return m_stepSize; +} + void NzPhysWorld::SetGravity(const NzVector3f& gravity) { m_gravity = gravity; } -void NzPhysWorld::SetSize(const NzBoxf& box) -{ - NewtonSetWorldSize(m_world, box.GetPosition(), box.GetPosition()+box.GetSize()); -} - -void NzPhysWorld::SetSize(const NzVector3f& min, const NzVector3f& max) -{ - NewtonSetWorldSize(m_world, min, max); -} - void NzPhysWorld::SetSolverModel(unsigned int model) { NewtonSetSolverModel(m_world, model); } -void NzPhysWorld::Update(float timestep) +void NzPhysWorld::SetStepSize(float stepSize) { - NewtonUpdate(m_world, timestep); + m_stepSize = stepSize; +} + +void NzPhysWorld::Step(float timestep) +{ + m_timestepAccumulator += timestep; + + while (m_timestepAccumulator >= m_stepSize) + { + NewtonUpdate(m_world, m_stepSize); + m_timestepAccumulator -= m_stepSize; + } }