Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate physics force and impulse into their own components #880

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions engine/include/cubos/engine/physics/components/force.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// @file
/// @brief Component @ref cubos::engine::Force.
/// @ingroup physics-plugin

#pragma once

#include <glm/vec3.hpp>

#include <cubos/core/reflection/reflect.hpp>

namespace cubos::engine
{
/// @brief Component which holds forces applied on a particle.
/// @note Should be used with @ref Velocity.
/// @ingroup physics-plugin
struct Force
{
CUBOS_REFLECT;

glm::vec3 vec() const
{
return mForce;
}

void add(glm::vec3 force)
{
mForce += force;
}

void clear()
{
mForce = {0.0F, 0.0F, 0.0F};
}

private:
glm::vec3 mForce = {0.0F, 0.0F, 0.0F};
};

} // namespace cubos::engine
39 changes: 39 additions & 0 deletions engine/include/cubos/engine/physics/components/impulse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// @file
/// @brief Component @ref cubos::engine::Force.
/// @ingroup physics-plugin

#pragma once

#include <glm/vec3.hpp>

#include <cubos/core/reflection/reflect.hpp>

namespace cubos::engine
{
/// @brief Component which holds impulses applied on a particle.
/// @note Should be used with @ref Velocity.
/// @ingroup physics-plugin
struct Impulse
{
CUBOS_REFLECT;

glm::vec3 vec() const
{
return mImpulse;
}

void add(glm::vec3 impulse)
{
mImpulse += impulse;
}

void clear()
{
mImpulse = {0.0F, 0.0F, 0.0F};
}

private:
glm::vec3 mImpulse;
};

} // namespace cubos::engine
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// @file
/// @brief Component @ref cubos::engine::PhysicsMass.
/// @brief Component @ref cubos::engine::Mass.
/// @ingroup physics-plugin

#pragma once
Expand All @@ -12,7 +12,7 @@ namespace cubos::engine
{
/// @brief Component which defines the mass of a particle.
/// @ingroup physics-plugin
struct PhysicsMass
struct Mass
{
CUBOS_REFLECT;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// @file
/// @brief Component @ref cubos::engine::PhysicsVelocity.
/// @brief Component @ref cubos::engine::Velocity.
/// @ingroup physics-plugin

#pragma once
Expand All @@ -11,14 +11,12 @@
namespace cubos::engine
{
/// @brief Component which holds velocity and forces applied on a particle.
/// @note Should be used with @ref PhysicsMass and @ref Position.
/// @note Should be used with @ref Mass and @ref Position.
/// @ingroup physics-plugin
struct PhysicsVelocity
struct Velocity
{
CUBOS_REFLECT;

glm::vec3 velocity;
glm::vec3 force;
glm::vec3 impulse;
glm::vec3 vec;
};
} // namespace cubos::engine
12 changes: 8 additions & 4 deletions engine/include/cubos/engine/physics/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
#include <cubos/core/reflection/external/primitives.hpp>

#include <cubos/engine/physics/components/accumulated_correction.hpp>
#include <cubos/engine/physics/components/physics_mass.hpp>
#include <cubos/engine/physics/components/physics_velocity.hpp>
#include <cubos/engine/physics/components/force.hpp>
#include <cubos/engine/physics/components/impulse.hpp>
#include <cubos/engine/physics/components/mass.hpp>
#include <cubos/engine/physics/components/previous_position.hpp>
#include <cubos/engine/physics/components/velocity.hpp>
#include <cubos/engine/physics/plugins/gravity.hpp>
#include <cubos/engine/physics/resources/damping.hpp>
#include <cubos/engine/physics/resources/fixed_delta_time.hpp>
Expand All @@ -37,8 +39,10 @@ namespace cubos::engine
/// - @ref Substeps - holds the amount of substeps for the physics update.
///
/// ## Components
/// - @ref PhysicsVelocity - holds the information for moving an object straight.
/// - @ref PhysicsMass - holds the mass of an object.
/// - @ref Velocity - holds the information for moving an object straight.
/// - @ref Force - holds forces applied on a particle.
/// - @ref Impulse - holds impulses applied on a particle.
/// - @ref Mass - holds the mass of an object.
/// - @ref PreviousPosition - holds the previous position of the entity in a substep.
/// - @ref AccumulatedCorrection - holds the corrections accumulated from the constraints solving.
///
Expand Down
6 changes: 4 additions & 2 deletions engine/include/cubos/engine/physics/plugins/gravity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

#pragma once

#include <cubos/engine/physics/components/physics_mass.hpp>
#include <cubos/engine/physics/components/physics_velocity.hpp>
#include <cubos/engine/physics/components/force.hpp>
#include <cubos/engine/physics/components/impulse.hpp>
#include <cubos/engine/physics/components/mass.hpp>
#include <cubos/engine/physics/components/velocity.hpp>
#include <cubos/engine/physics/resources/gravity.hpp>
#include <cubos/engine/prelude.hpp>

Expand Down
15 changes: 8 additions & 7 deletions engine/samples/physics/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,26 @@ int main(int argc, char** argv)
.add(RenderableGrid{CarAsset, offset})
.add(Position{{0.0F, 0.0F, 0.0F}})
.add(PreviousPosition{{0.0F, 0.0F, 0.0F}})
.add(PhysicsVelocity{
.velocity = {0.0F, 0.0F, 0.0F}, .force = {0.0F, 0.0F, 0.0F}, .impulse = {0.0F, 0.0F, 0.0F}})
.add(PhysicsMass{.mass = 500.0F, .inverseMass = 1.0F / 500.0F})
.add(Velocity{.vec = {0.0F, 0.0F, 0.0F}})
.add(Force{})
.add(Impulse{})
.add(Mass{.mass = 500.0F, .inverseMass = 1.0F / 500.0F})
.add(AccumulatedCorrection{{0.0F, 0.0F, 0.0F}})
.add(LocalToWorld{});
});

cubos.system("push the car")
.tagged("cubos.physics.apply_forces")
.call([](Query<PhysicsVelocity&> query, MaxTime& time, const DeltaTime& deltaTime) {
for (auto [velocity] : query)
.call([](Query<Velocity&, Force&, Impulse&> query, MaxTime& time, const DeltaTime& deltaTime) {
for (auto [velocity, force, impulse] : query)
{
if (time.current < time.max)
{
if (time.current == 0.0F)
{
velocity.impulse += glm::vec3(0.0F, 5000.0F, 0.0F);
impulse.add(glm::vec3(0.0F, 5000.0F, 0.0F));
}
velocity.force += glm::vec3(0.0F, 0.0F, -5000.0F);
force.add(glm::vec3(0.0F, 0.0F, -5000.0F));
time.current += deltaTime.value;
}
}
Expand Down
6 changes: 3 additions & 3 deletions engine/src/cubos/engine/physics/gravity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ void cubos::engine::gravityPlugin(Cubos& cubos)

cubos.system("apply gravity")
.tagged("cubos.physics.apply_forces")
.call([](Query<PhysicsVelocity&, const PhysicsMass&> query, const Gravity& gravity) {
for (auto [velocity, mass] : query)
.call([](Query<Velocity&, Force&, const Mass&> query, const Gravity& gravity) {
for (auto [velocity, force, mass] : query)
{
if (mass.inverseMass <= 0.0F)
{
Expand All @@ -21,7 +21,7 @@ void cubos::engine::gravityPlugin(Cubos& cubos)
// Apply gravity force
glm::vec3 gravitationForce = mass.mass * gravity.value;

velocity.force += gravitationForce;
force.add(gravitationForce);
}
});
}
80 changes: 51 additions & 29 deletions engine/src/cubos/engine/physics/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,30 @@ CUBOS_REFLECT_IMPL(AccumulatedCorrection)
.build();
}

CUBOS_REFLECT_IMPL(PhysicsMass)
CUBOS_REFLECT_IMPL(Mass)
{
return cubos::core::ecs::TypeBuilder<PhysicsMass>("cubos::engine::PhysicsMass")
.withField("mass", &PhysicsMass::mass)
.withField("inverseMass", &PhysicsMass::inverseMass)
return cubos::core::ecs::TypeBuilder<Mass>("cubos::engine::Mass")
.withField("mass", &Mass::mass)
.withField("inverseMass", &Mass::inverseMass)
.build();
}

CUBOS_REFLECT_IMPL(PhysicsVelocity)
CUBOS_REFLECT_IMPL(Velocity)
{
return cubos::core::ecs::TypeBuilder<PhysicsVelocity>("cubos::engine::PhysicsVelocity")
.withField("velocity", &PhysicsVelocity::velocity)
.withField("force", &PhysicsVelocity::force)
.withField("impulse", &PhysicsVelocity::impulse)
return cubos::core::ecs::TypeBuilder<Velocity>("cubos::engine::Velocity")
.withField("velocity", &Velocity::vec)
.build();
}

CUBOS_REFLECT_IMPL(Force)
{
return cubos::core::ecs::TypeBuilder<Force>("cubos::engine::Force").withField("mForce", &Force::mForce).build();
}

CUBOS_REFLECT_IMPL(Impulse)
{
return cubos::core::ecs::TypeBuilder<Impulse>("cubos::engine::Impulse")
.withField("mImpulse", &Impulse::mImpulse)
.build();
}

Expand All @@ -46,18 +56,20 @@ static bool simulatePhysicsStep(PhysicsAccumulator& accumulator, const FixedDelt

void cubos::engine::physicsPlugin(Cubos& cubos)
{
cubos.addPlugin(gravityPlugin);

cubos.addResource<FixedDeltaTime>();
cubos.addResource<Substeps>();
cubos.addResource<PhysicsAccumulator>();
cubos.addResource<Damping>();

cubos.addComponent<PhysicsVelocity>();
cubos.addComponent<PhysicsMass>();
cubos.addComponent<Velocity>();
cubos.addComponent<Force>();
cubos.addComponent<Impulse>();
cubos.addComponent<Mass>();
cubos.addComponent<AccumulatedCorrection>();
cubos.addComponent<PreviousPosition>();

cubos.addPlugin(gravityPlugin);

// executed every frame
cubos.system("increase fixed-step accumulator")
.tagged("cubos.physics.simulation.prepare")
Expand All @@ -74,22 +86,22 @@ void cubos::engine::physicsPlugin(Cubos& cubos)
.after("cubos.physics.apply_forces")
.before("cubos.physics.simulation.substeps.integrate")
.onlyIf(simulatePhysicsStep)
.call([](Query<PhysicsVelocity&, const PhysicsMass&> query) {
for (auto [velocity, mass] : query)
.call([](Query<Velocity&, const Impulse&, const Mass&> query) {
for (auto [velocity, impulse, mass] : query)
{
velocity.velocity += velocity.impulse * mass.inverseMass;
velocity.vec += impulse.vec() * mass.inverseMass;
}
});

cubos.system("integrate position")
.tagged("cubos.physics.simulation.substeps.integrate")
.after("cubos.physics.simulation.prepare")
.onlyIf(simulatePhysicsStep)
.call([](Query<Position&, PreviousPosition&, PhysicsVelocity&, const PhysicsMass&> query,
.call([](Query<Position&, PreviousPosition&, Velocity&, const Force&, const Mass&> query,
const Damping& damping, const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps) {
float subDeltaTime = fixedDeltaTime.value / (float)substeps.value;

for (auto [position, prevPosition, velocity, mass] : query)
for (auto [position, prevPosition, velocity, force, mass] : query)
{
prevPosition.vec = position.vec;

Expand All @@ -99,13 +111,13 @@ void cubos::engine::physicsPlugin(Cubos& cubos)
}

// Apply damping
velocity.velocity *= glm::pow(damping.value, subDeltaTime);
velocity.vec *= glm::pow(damping.value, subDeltaTime);

// Apply external forces
glm::vec3 deltaLinearVelocity = velocity.force * mass.inverseMass * subDeltaTime;
glm::vec3 deltaLinearVelocity = force.vec() * mass.inverseMass * subDeltaTime;

velocity.velocity += deltaLinearVelocity;
position.vec += velocity.velocity * subDeltaTime;
velocity.vec += deltaLinearVelocity;
position.vec += velocity.vec * subDeltaTime;
}
});

Expand All @@ -125,25 +137,35 @@ void cubos::engine::physicsPlugin(Cubos& cubos)
.tagged("cubos.physics.simulation.substeps.update_velocity")
.after("cubos.physics.simulation.substeps.correct_position")
.onlyIf(simulatePhysicsStep)
.call([](Query<const Position&, const PreviousPosition&, PhysicsVelocity&> query,
const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps) {
.call([](Query<const Position&, const PreviousPosition&, Velocity&> query, const FixedDeltaTime& fixedDeltaTime,
const Substeps& substeps) {
float subDeltaTime = fixedDeltaTime.value / (float)substeps.value;

for (auto [position, prevPosition, velocity] : query)
{
velocity.velocity = (position.vec - prevPosition.vec) / subDeltaTime;
velocity.vec = (position.vec - prevPosition.vec) / subDeltaTime;
}
});

cubos.system("clear forces")
.tagged("cubos.physics.simulation.clear_forces")
.after("cubos.physics.simulation.substeps.update_velocity")
.onlyIf(simulatePhysicsStep)
.call([](Query<PhysicsVelocity&> query) {
for (auto [velocity] : query)
.call([](Query<Force&> query) {
for (auto [force] : query)
{
force.clear();
}
});

cubos.system("clear impulses")
.tagged("cubos.physics.simulation.clear_forces")
.after("cubos.physics.simulation.substeps.update_velocity")
.onlyIf(simulatePhysicsStep)
.call([](Query<Impulse&> query) {
for (auto [impulse] : query)
{
velocity.force = glm::vec3(0, 0, 0);
velocity.impulse = glm::vec3(0, 0, 0);
impulse.clear();
}
});

Expand Down
Loading