First steps towards Catmul-Rom spline path movement

Lots of hardcoded stuff, but interpolation between two points is working and displayed.
This commit is contained in:
karl 2020-09-28 16:52:35 +02:00
parent f1eaecde89
commit 8f3d3dc7bf
5 changed files with 142 additions and 4 deletions

View File

@ -7,8 +7,8 @@ find_package(OpenGL REQUIRED)
find_package(glfw3 REQUIRED)
find_package(glm REQUIRED)
add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h ECS/Components/SineAnimation.h ECS/Systems/SineAnimationSystem.h ECS/Components/DirectionalLight.h Rendering/Material.h)
add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Components/PathMove.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h ECS/Components/SineAnimation.h ECS/Systems/SineAnimationSystem.h ECS/Components/DirectionalLight.h Rendering/Material.h ECS/Systems/PathMoveSystem.h)
include_directories(${OPENGL_INCLUDE_DIRS})
target_link_libraries(ecsgame ${OPENGL_LIBRARY} glfw glm ${CMAKE_DL_LIBS})
target_link_libraries(ecsgame ${OPENGL_LIBRARY} glfw glm ${CMAKE_DL_LIBS})

22
ECS/Components/PathMove.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __PATHMOVE_H__
#define __PATHMOVE_H__
#include <glm/glm.hpp>
#include <vector>
struct PathMove {
struct Path {
std::vector<glm::vec3> points;
};
PathMove(double speed) : speed(speed) {}
double speed;
Path path;
int current_point_index;
float time_passed = 0.0;
};
#endif // __PATHMOVE_H__

View File

@ -30,6 +30,11 @@ struct Transform {
matrix = glm::rotate(matrix, glm::radians(degrees), axis);
}
void set_position(glm::vec3 position) {
glm::vec3 difference = getPosition() - position;
translate(-difference);
}
glm::vec3 getPosition() const {
return matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
}

View File

@ -0,0 +1,107 @@
#ifndef __PATHMOVESYSTEM_H__
#define __PATHMOVESYSTEM_H__
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "../ECS.h"
#include "../Components/Transform.h"
#include "../Events/InputEvent.h"
#include "../Components/PathMove.h"
using namespace ECS;
// Spline helper functions
// Calculate the t value for a CatmullRom spline
float get_t(float alpha, float t, glm::vec3 p0, glm::vec3 p1) {
float a = pow((p1.x - p0.x), 2.0f) + pow((p1.y - p0.y), 2.0f) + pow((p1.z - p0.z), 2.0f);
float b = pow(a, alpha * 0.5f);
return (b + t);
}
// Given four points, calculate an interpolated point between p1 and p2 using a Catmul-Rom spline.
// t specifies the position along the path, with t=0 being p1 and t=2 being p2.
glm::vec3 catmul(float alpha, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 p3, float t) {
float t0 = 0.0f;
float t1 = get_t(alpha, t0, p0, p1);
float t2 = get_t(alpha, t1, p1, p2);
float t3 = get_t(alpha, t2, p2, p3);
// Lerp t to be between t1 and t2
t = t1 + t * (t2 - t1);
glm::vec3 A1 = (t1-t)/(t1-t0)*p0 + (t-t0)/(t1-t0)*p1;
glm::vec3 A2 = (t2-t)/(t2-t1)*p1 + (t-t1)/(t2-t1)*p2;
glm::vec3 A3 = (t3-t)/(t3-t2)*p2 + (t-t2)/(t3-t2)*p3;
glm::vec3 B1 = (t2-t)/(t2-t0)*A1 + (t-t0)/(t2-t0)*A2;
glm::vec3 B2 = (t3-t)/(t3-t1)*A2 + (t-t1)/(t3-t1)*A3;
glm::vec3 C = (t2-t)/(t2-t1)*B1 + (t-t1)/(t2-t1)*B2;
return C;
}
class PathMoveSystem : public EntitySystem, public EventSubscriber<InputEvent> {
void configure(World *pWorld) override {
myWorld = pWorld;
// TODO: Changing velocity
myWorld->subscribe<InputEvent>(this);
}
void receive(World *pWorld, const InputEvent &event) override {
if (event.key == GLFW_KEY_W) {
myWorld->each<PathMove>([&](Entity *ent, ComponentHandle<PathMove> pathmove) {
if (event.action == GLFW_PRESS) {
// TODO: Velocity adder
} else if (event.action == GLFW_RELEASE) {
// TODO
}
});
} else if (event.key == GLFW_KEY_S) {
myWorld->each<PathMove>([&](Entity *ent, ComponentHandle<PathMove> pathmove) {
if (event.action == GLFW_PRESS) {
// TODO
} else if (event.action == GLFW_RELEASE) {
// TODO
}
});
}
}
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) {
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);
transform->set_position(point);
});
}
void unconfigure(World *pWorld) override {
pWorld->unsubscribeAll(this);
}
private:
World *myWorld;
};
#endif // __PATHMOVESYSTEM_H__

View File

@ -12,11 +12,13 @@
#include "ECS/Systems/KeyboardMovementSystem.h"
#include "ECS/Systems/RenderSystem.h"
#include "ECS/Systems/MouseLookSystem.h"
#include "ECS/Systems/PathMoveSystem.h"
#include "ECS/Components/ObjMesh.h"
#include "ECS/Components/Texture.h"
#include "ECS/Components/SineAnimation.h"
#include "ECS/Systems/SineAnimationSystem.h"
#include "ECS/Components/DirectionalLight.h"
#include "ECS/Components/PathMove.h"
using namespace ECS;
@ -78,6 +80,7 @@ int main() {
// world->registerSystem(new PositionDebugOutputSystem());
world->registerSystem(new KeyboardMovementSystem());
world->registerSystem(new MouseLookSystem(1280, 720));
world->registerSystem(new PathMoveSystem());
world->registerSystem(new SineAnimationSystem());
RenderSystem* renderSystem = new RenderSystem();
@ -85,9 +88,10 @@ int main() {
Entity *player = world->create();
player->assign<Transform>();
player->assign<Movement>(glm::vec3(2.f, 2.f, 2.f));
//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<MouseLook>(0.1);
player->assign<PathMove>(10.0);
player->get<Transform>()->translate(glm::vec3(0.0f, 1.0f, 2.0f));
Entity *monkey = world->create();