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.
This commit is contained in:
karl 2020-09-28 18:14:20 +02:00
parent 80b4aa7ba8
commit d6effd66f6
3 changed files with 72 additions and 16 deletions

View File

@ -6,16 +6,18 @@
struct PathMove {
struct Path {
Path(std::vector<glm::vec3> points) : points(points) {}
std::vector<glm::vec3> 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;
};

View File

@ -75,24 +75,70 @@ class PathMoveSystem : public EntitySystem, public EventSubscriber<InputEvent> {
}
void tick(World *pWorld, float deltaTime) override {
PathMove::Path path;
path.points = std::vector<glm::vec3>{
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<Transform, PathMove>(
[&](Entity *ent, ComponentHandle<Transform> transform, ComponentHandle<PathMove> 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;
});
}

View File

@ -91,7 +91,15 @@ int main() {
//player->assign<Movement>(glm::vec3(2.f, 2.f, 2.f));
//player->assign<MouseLook>(0.1);
player->assign<Camera>(70.0f, 1280, 720, 0.1f, 100.0f);
player->assign<PathMove>(10.0);
player->assign<PathMove>(10.0, PathMove::Path(std::vector<glm::vec3>{
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<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f));
Entity *monkey = world->create();