Skip to content

Commit 11eb603

Browse files
committed
feat(physics): Interpolation
things
1 parent c1ec1e2 commit 11eb603

11 files changed

Lines changed: 183 additions & 7 deletions

File tree

engine/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ set(CUBOS_ENGINE_SOURCE
239239
"src/tools/ecs_statistics/plugin.cpp"
240240
"src/tools/console/plugin.cpp"
241241
"src/tools/plugin.cpp"
242+
243+
"src/interpolation/plugin.cpp"
242244
)
243245

244246
# ---------------------- Configure engine library target ----------------------
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// @dir
2+
/// @brief @ref interpolation-plugin plugin directory.
3+
4+
/// @file
5+
/// @brief Plugin entry point.
6+
/// @ingroup interpolation-plugin
7+
8+
#pragma once
9+
10+
#include <glm/glm.hpp>
11+
#include <glm/gtx/quaternion.hpp>
12+
13+
#include <cubos/core/reflection/reflect.hpp>
14+
#include <cubos/core/reflection/type.hpp>
15+
16+
#include <cubos/engine/api.hpp>
17+
#include <cubos/engine/prelude.hpp>
18+
19+
namespace cubos::engine
20+
{
21+
22+
/// @brief Component which holds the the previous and next frames position, rotation and scale for interpolation.
23+
/// @ingroup interpolation-plugin
24+
struct CUBOS_ENGINE_API Interpolated
25+
{
26+
CUBOS_REFLECT;
27+
28+
glm::vec3 currentPosition; ///< Currently interpolated frame position.
29+
// glm::quat currentRotation; ///< Currently interpolated frame rotation.
30+
float currentScale; ///< Currently interpolated frame scale factor.
31+
32+
glm::vec3 previousPosition; ///< Previous frame position.
33+
// glm::quat previousRotation; ///< Previous frame rotation.
34+
float previousScale; ///< Previous frame scale factor.
35+
36+
glm::vec3 nextPosition; ///< Next frame position.
37+
// glm::quat nextRotation; ///< Next frame rotation.
38+
float nextScale; ///< Next frame scale factor.
39+
};
40+
41+
/// @ingroup interpolation-plugin
42+
/// @brief Interpolates position, rotation and scale of entities with the @ref Interpolated component in between
43+
/// fixed updates.
44+
45+
/// @brief Plugin entry function.
46+
/// @param cubos @b Cubos main class
47+
/// @ingroup interpolation-plugin
48+
void interpolationPlugin(Cubos& cubos);
49+
} // namespace cubos::engine

engine/samples/collisions/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <cubos/engine/gizmos/plugin.hpp>
1717
#include <cubos/engine/gizmos/target.hpp>
1818
#include <cubos/engine/input/plugin.hpp>
19+
#include <cubos/engine/interpolation/plugin.hpp>
1920
#include <cubos/engine/physics/plugin.hpp>
2021
#include <cubos/engine/physics/solver/plugin.hpp>
2122
#include <cubos/engine/render/camera/camera.hpp>
@@ -124,6 +125,7 @@ int main(int argc, char** argv)
124125
.add(Position{glm::vec3{0.0F, 0.0F, -2.0F}})
125126
.add(Rotation{})
126127
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 1.0F}})
128+
.add(Interpolated{})
127129
.entity();
128130
state.aRotationAxis = glm::sphericalRand(1.0F);
129131

@@ -135,6 +137,7 @@ int main(int argc, char** argv)
135137
.add(Position{glm::vec3{0.0F, 0.0F, 2.0F}})
136138
.add(Rotation{})
137139
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, -1.0F}})
140+
.add(Interpolated{})
138141
.entity();
139142
state.bRotationAxis = glm::sphericalRand(1.0F);
140143
});

engine/samples/complex_physics/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cubos/engine/collisions/shapes/box.hpp>
99
#include <cubos/engine/fixed_step/plugin.hpp>
1010
#include <cubos/engine/gizmos/plugin.hpp>
11+
#include <cubos/engine/interpolation/plugin.hpp>
1112
#include <cubos/engine/physics/plugin.hpp>
1213
#include <cubos/engine/physics/plugins/gravity.hpp>
1314
#include <cubos/engine/physics/solver/plugin.hpp>
@@ -150,6 +151,7 @@ int main(int argc, char** argv)
150151
{
151152
auto builder = cmds.spawn(red ? redCube->blueprint() : whiteCube->blueprint());
152153
builder.add(Position{.vec = nextPosition});
154+
builder.add(Interpolated{});
153155
nextPosition.y += 1.0F;
154156
red = !red;
155157
}
@@ -172,6 +174,7 @@ int main(int argc, char** argv)
172174
auto builder = cmds.spawn(cube->blueprint());
173175
glm::vec3 position = RandomDirection ? randomPosition() : glm::vec3{0.0F, 3.0F, -7.0F};
174176
builder.add(Position{.vec = position});
177+
builder.add(Interpolated{});
175178

176179
// push cube in direction to the center
177180
glm::vec3 impulseDirection = calculateDirection(position);

engine/samples/distance_constraint/main.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cubos/engine/gizmos/plugin.hpp>
1616
#include <cubos/engine/gizmos/target.hpp>
1717
#include <cubos/engine/input/plugin.hpp>
18+
#include <cubos/engine/interpolation/plugin.hpp>
1819
#include <cubos/engine/physics/constraints/distance_constraint.hpp>
1920
#include <cubos/engine/physics/plugin.hpp>
2021
#include <cubos/engine/physics/solver/plugin.hpp>
@@ -74,6 +75,7 @@ void createScenario(Commands& commands, State& state, Options& options)
7475
.add(Position{glm::vec3{0.0F, 0.0F, -2.0F}})
7576
.add(Rotation{})
7677
.add(PhysicsBundle{.mass = 10000000000000000.0F, .velocity = {0.0F, 0.0F, 0.0F}})
78+
.add(Interpolated{})
7779
.entity();
7880

7981
state.b = commands.create()
@@ -84,6 +86,7 @@ void createScenario(Commands& commands, State& state, Options& options)
8486
.add(Position{glm::vec3{0.0F, 0.0F, 2.0F}})
8587
.add(Rotation{})
8688
.add(PhysicsBundle{.mass = 500.0F, .velocity = {1.0F, 0.0F, 1.0F}})
89+
.add(Interpolated{})
8790
.entity();
8891

8992
commands.relate(state.a, state.b,
@@ -103,6 +106,7 @@ void createScenario(Commands& commands, State& state, Options& options)
103106
.add(Position{glm::vec3{0.0F, 0.0F, 0.0F}})
104107
.add(Rotation{})
105108
.add(PhysicsBundle{.mass = 10000000000000000.0F, .velocity = {0.0F, 0.0F, 0.0F}})
109+
.add(Interpolated{})
106110
.entity();
107111

108112
state.b = commands.create()
@@ -113,6 +117,7 @@ void createScenario(Commands& commands, State& state, Options& options)
113117
.add(Position{glm::vec3{0.0F, 0.0F, 5.0F}})
114118
.add(Rotation{})
115119
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 0.0F}})
120+
.add(Interpolated{})
116121
.entity();
117122

118123
commands.relate(state.a, state.b,
@@ -132,6 +137,7 @@ void createScenario(Commands& commands, State& state, Options& options)
132137
.add(Position{glm::vec3{0.0F, 0.0F, 0.0F}})
133138
.add(Rotation{})
134139
.add(PhysicsBundle{.mass = 10000000000000000.0F, .velocity = {0.0F, 0.0F, 0.0F}})
140+
.add(Interpolated{})
135141
.entity();
136142

137143
state.b = commands.create()
@@ -142,6 +148,7 @@ void createScenario(Commands& commands, State& state, Options& options)
142148
.add(Position{glm::vec3{0.0F, 0.0F, 5.0F}})
143149
.add(Rotation{})
144150
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 0.0F}})
151+
.add(Interpolated{})
145152
.entity();
146153

147154
state.c = commands.create()
@@ -152,6 +159,7 @@ void createScenario(Commands& commands, State& state, Options& options)
152159
.add(Position{glm::vec3{0.0F, 0.0F, 10.0F}})
153160
.add(Rotation{})
154161
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 0.0F}})
162+
.add(Interpolated{})
155163
.entity();
156164

157165
commands.relate(state.a, state.b,
@@ -178,6 +186,7 @@ void createScenario(Commands& commands, State& state, Options& options)
178186
.add(Position{glm::vec3{0.0F, 0.0F, 0.0F}})
179187
.add(Rotation{})
180188
.add(PhysicsBundle{.mass = 10000000000000000.0F, .velocity = {0.0F, 0.0F, 0.0F}})
189+
.add(Interpolated{})
181190
.entity();
182191

183192
state.b = commands.create()
@@ -188,6 +197,7 @@ void createScenario(Commands& commands, State& state, Options& options)
188197
.add(Position{glm::vec3{0.0F, 0.0F, -5.0F}})
189198
.add(Rotation{})
190199
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 0.0F}})
200+
.add(Interpolated{})
191201
.entity();
192202

193203
state.c = commands.create()
@@ -198,6 +208,7 @@ void createScenario(Commands& commands, State& state, Options& options)
198208
.add(Position{glm::vec3{0.0F, 0.0F, -15.0F}})
199209
.add(Rotation{})
200210
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 5.0F}})
211+
.add(Interpolated{})
201212
.entity();
202213

203214
commands.relate(state.a, state.b,

engine/samples/voxel-shape-collisions/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <cubos/engine/fixed_step/plugin.hpp>
1818
#include <cubos/engine/gizmos/plugin.hpp>
1919
#include <cubos/engine/gizmos/target.hpp>
20+
#include <cubos/engine/interpolation/plugin.hpp>
2021
#include <cubos/engine/physics/plugin.hpp>
2122
#include <cubos/engine/physics/solver/plugin.hpp>
2223
#include <cubos/engine/render/camera/camera.hpp>
@@ -107,6 +108,7 @@ int main()
107108
.add(Position{glm::vec3{0.0F, -10.0F, -20.0F}})
108109
.add(Rotation{})
109110
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 1.0F}})
111+
.add(Interpolated{})
110112
.entity();
111113
state.aRotationAxis = glm::sphericalRand(1.0F);
112114

@@ -122,6 +124,7 @@ int main()
122124
.velocity = {0.0F, 0.0F, -1.0F},
123125
.material = PhysicsMaterial{.bounciness = 0.0},
124126
.inertiaTensor = glm::mat3(0.0F)})
127+
.add(Interpolated{})
125128
.entity();
126129
state.bRotationAxis = glm::sphericalRand(1.0F);
127130
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include <glm/glm.hpp>
2+
3+
#include <cubos/core/ecs/reflection.hpp>
4+
#include <cubos/core/reflection/external/glm.hpp>
5+
#include <cubos/core/reflection/type.hpp>
6+
7+
#include <cubos/engine/fixed_step/plugin.hpp>
8+
#include <cubos/engine/interpolation/plugin.hpp>
9+
#include <cubos/engine/physics/plugin.hpp>
10+
#include <cubos/engine/physics/solver/plugin.hpp>
11+
#include <cubos/engine/transform/plugin.hpp>
12+
13+
using namespace cubos::engine;
14+
15+
CUBOS_REFLECT_IMPL(cubos::engine::Interpolated)
16+
{
17+
return cubos::core::ecs::TypeBuilder<Interpolated>("cubos::engine::Interpolated").build();
18+
}
19+
20+
void cubos::engine::interpolationPlugin(Cubos& cubos)
21+
{
22+
cubos.depends(fixedStepPlugin);
23+
cubos.depends(transformPlugin);
24+
cubos.depends(physicsPlugin);
25+
cubos.depends(physicsSolverPlugin);
26+
27+
cubos.component<Interpolated>();
28+
29+
cubos.observer("set up Interpolated")
30+
.onAdd<Interpolated>()
31+
.call([](Query<Entity, Interpolated&, const Position&, const Rotation&, const Scale&> query) {
32+
for (auto [ent, interp, position, rotation, scale] : query)
33+
{
34+
interp.previousPosition = position.vec;
35+
// interp.previousRotation = rotation.quat;
36+
interp.previousScale = scale.factor;
37+
interp.nextPosition = position.vec;
38+
// interp.nextRotation = rotation.quat;
39+
interp.nextScale = scale.factor;
40+
}
41+
});
42+
43+
cubos.system("prepare before update")
44+
.tagged(fixedStepTag)
45+
.before(physicsFinalizePositionTag)
46+
.call([](Query<const Position&, const Rotation&, const Scale&, Interpolated&> query) {
47+
for (auto [position, rotation, scale, interpolated] : query)
48+
{
49+
interpolated.previousPosition = interpolated.nextPosition;
50+
// interpolated.previousRotation = interpolated.nextRotation;
51+
interpolated.previousScale = interpolated.nextScale;
52+
}
53+
});
54+
55+
cubos.system("do interpolation on Interpolated entities")
56+
.after(fixedStepTag)
57+
.call([](const FixedAccumulatedTime& acc, const DeltaTime& dt, const FixedDeltaTime& fdt,
58+
Query<Position&, Rotation&, Scale&, Interpolated&> query) {
59+
float alpha = (acc.value + dt.value()) / fdt.value;
60+
61+
for (auto [position, rotation, scale, interpolated] : query)
62+
{
63+
64+
if (position.vec == interpolated.currentPosition)
65+
{
66+
position.vec = glm::mix(interpolated.previousPosition, interpolated.nextPosition, alpha);
67+
}
68+
else
69+
{
70+
interpolated.previousPosition = position.vec;
71+
interpolated.nextPosition = position.vec;
72+
}
73+
interpolated.currentPosition = position.vec;
74+
75+
/*
76+
if (rotation.quat == interpolated.currentRotation)
77+
{
78+
rotation.quat = glm::slerp(interpolated.previousRotation, interpolated.nextRotation, alpha);
79+
}
80+
else
81+
{
82+
interpolated.previousRotation = rotation.quat;
83+
interpolated.nextRotation = rotation.quat;
84+
}
85+
interpolated.currentRotation = rotation.quat;
86+
*/
87+
88+
if (scale.factor == interpolated.nextScale)
89+
{
90+
scale.factor = glm::mix(interpolated.previousScale, interpolated.nextScale, alpha);
91+
}
92+
else
93+
{
94+
interpolated.previousScale = scale.factor;
95+
interpolated.nextScale = scale.factor;
96+
}
97+
interpolated.currentScale = scale.factor;
98+
}
99+
});
100+
}

engine/src/physics/solver/distance_constraint/plugin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,4 @@ void cubos::engine::distanceConstraintPlugin(Cubos& cubos)
245245
angVelocity2.vec += inertia2.inverseInertia * glm::cross(r2, p);
246246
}
247247
});
248-
}
248+
}

engine/src/physics/solver/integration/plugin.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <glm/glm.hpp>
44

55
#include <cubos/engine/fixed_step/plugin.hpp>
6+
#include <cubos/engine/interpolation/plugin.hpp>
67
#include <cubos/engine/physics/components/accumulated_correction.hpp>
78
#include <cubos/engine/physics/plugin.hpp>
89
#include <cubos/engine/physics/solver/plugin.hpp>
@@ -21,6 +22,7 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
2122
cubos.depends(transformPlugin);
2223
cubos.depends(physicsPlugin);
2324
cubos.depends(physicsSolverPlugin);
25+
cubos.depends(interpolationPlugin);
2426

2527
cubos.tag(physicsApplyImpulsesTag);
2628
cubos.tag(physicsClearForcesTag).after(physicsFinalizePositionTag).tagged(fixedStepTag);
@@ -95,14 +97,14 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
9597

9698
cubos.system("integrate delta position")
9799
.tagged(physicsIntegratePositionTag)
98-
.call([](Query<AccumulatedCorrection&, Rotation&, const Velocity&, const AngularVelocity&, const Mass&,
100+
.call([](Query<AccumulatedCorrection&, const Velocity&, Rotation&, const AngularVelocity&, const Mass&,
99101
const Inertia&>
100102
query,
101103
const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps,
102104
const SolverConstants& solverConstants) {
103105
float subDeltaTime = fixedDeltaTime.value / (float)substeps.value;
104106

105-
for (auto [correction, rotation, velocity, angVelocity, mass, inertia] : query)
107+
for (auto [correction, velocity, rotation, angVelocity, mass, inertia] : query)
106108
{
107109
// Position
108110
if (mass.inverseMass <= solverConstants.minInvMass)
@@ -126,15 +128,16 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
126128

127129
cubos.system("finalize position")
128130
.tagged(physicsFinalizePositionTag)
129-
.call([](Query<Position&, AccumulatedCorrection&, const Mass&> query, const SolverConstants& solverConstants) {
130-
for (auto [position, correction, mass] : query)
131+
.call([](Query<Position&, AccumulatedCorrection&, const Mass&, Interpolated&> query,
132+
const SolverConstants& solverConstants) {
133+
for (auto [position, correction, mass, interpolated] : query)
131134
{
132135
if (mass.inverseMass <= solverConstants.minInvMass)
133136
{
134137
continue;
135138
}
136139

137-
position.vec += correction.position;
140+
interpolated.nextPosition += correction.position;
138141
correction.position = glm::vec3(0.0F);
139142
}
140143
});

engine/src/physics/solver/penetration_constraint/plugin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,4 +586,4 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos)
586586
cmds.unrelate<PenetrationConstraints>(entity, other);
587587
}
588588
});
589-
}
589+
}

0 commit comments

Comments
 (0)