From d6effd66f61868b1ac4daaa9e382b27f3df2e14e Mon Sep 17 00:00:00 2001 From: karl Date: Mon, 28 Sep 2020 18:14:20 +0200 Subject: [PATCH] Finish basic spline movement The speed isn't chosen correctly yet, but the basic movement along the spline is functional! There are opportunities for a performance increase: Some calculations which we currently do every frame, are actually only necessary once we choose a new point for moving towards. --- ECS/Components/PathMove.h | 6 ++- ECS/Systems/PathMoveSystem.h | 72 +++++++++++++++++++++++++++++------- main.cpp | 10 ++++- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/ECS/Components/PathMove.h b/ECS/Components/PathMove.h index 2af6daf..dc0a1dc 100644 --- a/ECS/Components/PathMove.h +++ b/ECS/Components/PathMove.h @@ -6,16 +6,18 @@ struct PathMove { struct Path { + Path(std::vector points) : points(points) {} + std::vector points; }; - PathMove(double speed) : speed(speed) {} + PathMove(double speed, Path path) : speed(speed), path(path) {} double speed; Path path; - int current_point_index; + int current_point_index = 0; float time_passed = 0.0; }; diff --git a/ECS/Systems/PathMoveSystem.h b/ECS/Systems/PathMoveSystem.h index fe471d6..c856e5b 100644 --- a/ECS/Systems/PathMoveSystem.h +++ b/ECS/Systems/PathMoveSystem.h @@ -75,24 +75,70 @@ class PathMoveSystem : public EntitySystem, public EventSubscriber { } void tick(World *pWorld, float deltaTime) override { - PathMove::Path path; - - path.points = std::vector{ - glm::vec3(0.0, 2.0, 0.0), - glm::vec3(0.0, 2.0, 1.0), - glm::vec3(2.0, 2.0, 2.0), - glm::vec3(1.0, 3.0, 3.0), - glm::vec3(-2.0, 2.0, 4.0), - glm::vec3(2.0, 2.0, 4.0), - }; - pWorld->each( [&](Entity *ent, ComponentHandle transform, ComponentHandle pathmove) { + // Shorthand for the path (we'll use this a lot) + PathMove::Path path = pathmove->path; + + // Add the passed time pathmove->time_passed += deltaTime; - // Move from the second to the third point for now - glm::vec3 point = catmul(0.5f, path.points[0], path.points[1], path.points[2], path.points[3], pathmove->time_passed * 0.5); + // Shorthand for number of points in the path + int num_points = path.points.size(); + + if (pathmove->time_passed >= 1.0) { + // If we passed the last target, set the current_point_index to that target + pathmove->time_passed -= 1.0; + pathmove->current_point_index += 1; + + // If the point index is greater than the second to last one, reset + // (The point index specifies the point we're coming from, not the one we're moving towards) + if (pathmove->current_point_index >= num_points - 1) { + pathmove->current_point_index = 0; + } + } + + // The four points which are needed for the spline + // p1 and p2 are always the same (the current origin and the current target), but the rest depends on edge cases + glm::vec3 p0; + glm::vec3 p1 = path.points[pathmove->current_point_index]; + glm::vec3 p2 = path.points[pathmove->current_point_index + 1]; + glm::vec3 p3; + + if (pathmove->current_point_index == num_points - 2) { + // We're moving towards the last point, so the point after that needs to be interpolated. + // We interpolate linearly along the line from this point to the target point. + glm::vec3 interp_direction = p2 - p1; + p3 = p2 + interp_direction * 2.0f; + } else { + // We're fine - use the point after the target for p3 + p2 = path.points[pathmove->current_point_index + 1]; + p3 = path.points[pathmove->current_point_index + 2]; + } + + if (pathmove->current_point_index == 0) { + // We're at the first point, so the point before this needs to be interpolated. + // We interpolate linearly along the line from this to the next point (backwards). + glm::vec3 interp_direction = path.points[pathmove->current_point_index] - path.points[pathmove->current_point_index + 1]; + p0 = path.points[pathmove->current_point_index] + interp_direction; + } else { + // We're fine - use the point before the current point + p0 = path.points[pathmove->current_point_index - 1]; + } + + // Calculate the point on the spline + glm::vec3 point = catmul(0.5f, + p0, + p1, + p2, + p3, + pathmove->time_passed); + + // Apply transform->set_position(point); + + // FIXME: Debugging output + std::cout << point.x << ", " << point.y << ", " << point.z << std::endl; }); } diff --git a/main.cpp b/main.cpp index d178147..a260283 100644 --- a/main.cpp +++ b/main.cpp @@ -91,7 +91,15 @@ int main() { //player->assign(glm::vec3(2.f, 2.f, 2.f)); //player->assign(0.1); player->assign(70.0f, 1280, 720, 0.1f, 100.0f); - player->assign(10.0); + player->assign(10.0, PathMove::Path(std::vector{ + glm::vec3(0.0, 2.0, 0.0), + glm::vec3(0.0, 2.0, 1.0), + glm::vec3(2.0, 2.0, 2.0), + glm::vec3(1.0, 3.0, 3.0), + glm::vec3(-2.0, 2.0, 4.0), + glm::vec3(2.0, 2.0, 4.0), + glm::vec3(0.0, 2.0, 10.0) + })); player->get()->translate(glm::vec3(0.0f, 1.0f, 2.0f)); Entity *monkey = world->create();