252 lines
11 KiB
C++
252 lines
11 KiB
C++
#include <glad/glad.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include "ECS/Components/DirectionalLight.h"
|
|
#include "ECS/Components/Lines.h"
|
|
#include "ECS/Components/ObjMesh.h"
|
|
#include "ECS/Components/PathMove.h"
|
|
#include "ECS/Components/SineAnimation.h"
|
|
#include "ECS/Components/Texture.h"
|
|
#include "ECS/ECS.h"
|
|
#include "ECS/Events/InputEvent.h"
|
|
#include "ECS/Events/MouseMoveEvent.h"
|
|
#include "ECS/Systems/CollisionSystem.h"
|
|
#include "ECS/Systems/GravitySystem.h"
|
|
#include "ECS/Systems/InteractivePathSystem.h"
|
|
#include "ECS/Systems/KeyboardMovementSystem.h"
|
|
#include "ECS/Systems/MouseLookSystem.h"
|
|
#include "ECS/Systems/PathMoveSystem.h"
|
|
#include "ECS/Systems/PositionDebugSystem.h"
|
|
#include "ECS/Systems/RenderSystem.h"
|
|
#include "ECS/Systems/SineAnimationSystem.h"
|
|
#include "Rendering/Shader.h"
|
|
|
|
using namespace ECS;
|
|
|
|
World *world = World::createWorld();
|
|
|
|
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
|
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GLFW_TRUE);
|
|
|
|
world->emit<InputEvent>({key, action});
|
|
}
|
|
|
|
static void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
|
|
world->emit<MouseMoveEvent>({xpos, ypos});
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
// Parse command line parameters
|
|
int aa_samples = 4;
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
if (strcmp(argv[i], "-a") == 0) aa_samples = std::stoi(argv[i + 1]);
|
|
}
|
|
|
|
// TODO: Move this to RenderSystem?
|
|
GLFWwindow *window;
|
|
|
|
/* Initialize the library */
|
|
if (!glfwInit()) return -1;
|
|
|
|
// Anti Aliasing
|
|
glfwWindowHint(GLFW_SAMPLES, aa_samples);
|
|
|
|
/* Create a windowed mode window and its OpenGL context */
|
|
window = glfwCreateWindow(1280, 720, "ECSGame", NULL, NULL);
|
|
if (!window) {
|
|
glfwTerminate();
|
|
return -1;
|
|
}
|
|
|
|
/* Make the window's context current */
|
|
glfwMakeContextCurrent(window);
|
|
|
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
|
|
glfwSetCursorPosCallback(window, mouse_callback);
|
|
|
|
glfwSetKeyCallback(window, key_callback);
|
|
|
|
// glad: load all OpenGL function pointers
|
|
// ---------------------------------------
|
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
|
std::cout << "Failed to initialize GLAD" << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
// Transparency
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
// TODO: Could be automated by getting all classes within 'ECS/Systems'
|
|
// world->registerSystem(new GravitySystem(-9.8f));
|
|
// world->registerSystem(new PositionDebugOutputSystem());
|
|
world->registerSystem(new KeyboardMovementSystem());
|
|
world->registerSystem(new MouseLookSystem(1280, 720));
|
|
world->registerSystem(new PathMoveSystem());
|
|
world->registerSystem(new SineAnimationSystem());
|
|
world->registerSystem(new InteractivePathSystem());
|
|
|
|
// Create collision indicator
|
|
Entity *collision_point = world->create();
|
|
collision_point->assign<Transform>();
|
|
|
|
ObjMesh::Settings cp_obj_settings = ObjMesh::Settings();
|
|
cp_obj_settings.colliding = false;
|
|
collision_point->assign<ObjMesh>(ObjMesh("Resources/sphere.obj", cp_obj_settings));
|
|
|
|
collision_point->assign<Texture>("Resources/red.png", Texture::Settings(true), false);
|
|
collision_point->assign<Material>(0.1, 0.9);
|
|
|
|
CollisionSystem *collision_system = new CollisionSystem(collision_point);
|
|
world->registerSystem(collision_system);
|
|
|
|
RenderSystem *renderSystem = new RenderSystem();
|
|
world->registerSystem(renderSystem);
|
|
|
|
Entity *player = world->create();
|
|
player->assign<Transform>();
|
|
player->assign<Movement>(glm::vec3(5.f, 5.f, 5.f));
|
|
player->assign<MouseLook>(0.1);
|
|
player->assign<Camera>(70.0f, 900, 600, 0.1f, 100.0f);
|
|
player->assign<PathMove>(
|
|
3.0,
|
|
PathMove::Path(std::vector<glm::vec3>{glm::vec3(0.0, 2.0, 0.0), glm::vec3(0.0, 2.5, -1.0),
|
|
glm::vec3(0.0, 2.5, -2.0), glm::vec3(3.0, 3.0, -3.0),
|
|
glm::vec3(4.0, 2.0, -4.0), glm::vec3(3.0, 2.0, -5.0),
|
|
glm::vec3(0.0, 2.0, -10.0)}),
|
|
PathMove::Views(
|
|
std::vector<glm::quat>{glm::angleAxis(glm::radians(0.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(10.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(20.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(40.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(120.f), glm::vec3(0.f, 1.f, 0.f)),
|
|
glm::angleAxis(glm::radians(180.f), glm::vec3(0.f, 1.f, 0.f))}));
|
|
player->get<Transform>()->set_origin(glm::vec3(0.0, 3.0, 4.0));
|
|
|
|
Entity *monkey = world->create();
|
|
monkey->assign<Transform>();
|
|
monkey->assign<LODObjMesh>(std::vector<ObjMesh>{
|
|
ObjMesh("Resources/Monkey.obj", ObjMesh::Settings(0.0, 8.0, 0.4, 0.6, false)),
|
|
ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6, false))});
|
|
monkey->assign<Texture>("Resources/Marble010_2K_Color.jpg", Texture::Settings(true), false);
|
|
monkey->get<Texture>()->addNormalmap("Resources/Marble010_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5);
|
|
monkey->assign<Material>(0.6, 0.6);
|
|
monkey->get<Transform>()->set_origin(glm::vec3(0.0f, 2.0f, -6.0f));
|
|
|
|
Entity *wall1 = world->create();
|
|
wall1->assign<Transform>();
|
|
wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
|
|
wall1->assign<Texture>("Resources/Facade001_2K_Color.png", Texture::Settings(true), true);
|
|
wall1->get<Texture>()->addNormalmap("Resources/Facade001_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
wall1->assign<Material>(0.2, 0.8);
|
|
wall1->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -2.0f));
|
|
|
|
Entity *wall2 = world->create();
|
|
wall2->assign<Transform>();
|
|
wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
|
|
wall2->assign<Texture>("Resources/Facade001_2K_Color.png", Texture::Settings(true), true);
|
|
wall2->get<Texture>()->addNormalmap("Resources/Facade001_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
wall2->assign<Material>(0.2, 0.8);
|
|
wall2->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -10.0f));
|
|
|
|
Entity *wall3 = world->create();
|
|
wall3->assign<Transform>();
|
|
wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
|
|
wall3->assign<Texture>("Resources/Facade001_2K_Color.png", Texture::Settings(true), true);
|
|
wall3->get<Texture>()->addNormalmap("Resources/Facade001_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
wall3->assign<Material>(0.2, 0.8);
|
|
wall3->get<Transform>()->set_origin(glm::vec3(4.0f, 0.0f, -6.0f));
|
|
wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
|
|
|
|
Entity *wall4 = world->create();
|
|
wall4->assign<Transform>();
|
|
wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
|
|
wall4->assign<Texture>("Resources/Facade001_2K_Color.png", Texture::Settings(true), true);
|
|
wall4->get<Texture>()->addNormalmap("Resources/Facade001_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
wall4->assign<Material>(0.2, 0.8);
|
|
wall4->get<Transform>()->set_origin(glm::vec3(-4.0f, 0.0f, -6.0f));
|
|
wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
|
|
|
|
Entity *ground = world->create();
|
|
ground->assign<Transform>();
|
|
ground->assign<ObjMesh>(ObjMesh("Resources/Ground.obj", ObjMesh::Settings()));
|
|
ground->assign<Texture>("Resources/Ground003_2K_Color.jpg", Texture::Settings(true), false);
|
|
ground->get<Texture>()->addNormalmap("Resources/Ground003_2K_Normal.jpg",
|
|
Texture::Settings(true));
|
|
ground->assign<Material>(1.0, 0.0);
|
|
ground->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, 0.0f));
|
|
|
|
Entity *bench = world->create();
|
|
bench->assign<Transform>();
|
|
bench->assign<ObjMesh>(ObjMesh("Resources/bench.obj", ObjMesh::Settings()));
|
|
bench->assign<Texture>("Resources/Wood048_2K_Color.jpg", Texture::Settings(true), false);
|
|
bench->get<Texture>()->addNormalmap("Resources/Wood048_2K_Normal.jpg", Texture::Settings(true));
|
|
bench->assign<Material>(0.8, 0.2);
|
|
bench->get<Transform>()->set_origin(glm::vec3(8.0f, 0.0f, 0.0f));
|
|
bench->get<Transform>()->rotate(-90.0, glm::vec3(0.0, 1.0, 0.0));
|
|
|
|
Entity *ring = world->create();
|
|
ring->assign<Transform>();
|
|
ring->assign<ObjMesh>(ObjMesh("Resources/ring.obj", ObjMesh::Settings()));
|
|
ring->assign<Texture>("Resources/Metal007_2K_Color.jpg", Texture::Settings(true), false);
|
|
ring->get<Texture>()->addNormalmap("Resources/Metal007_2K_Normal.jpg", Texture::Settings(true));
|
|
ring->assign<Material>(0.1, 0.9);
|
|
ring->get<Transform>()->set_origin(glm::vec3(-5.0f, 2.0f, 0.0f));
|
|
|
|
Entity *sun = world->create();
|
|
sun->assign<DirectionalLight>(glm::normalize(glm::vec3(1.0, 1.0, 1.0)));
|
|
|
|
// We're done loading geometry -> build the collision structure
|
|
collision_system->build();
|
|
|
|
// Save the visualized kdtree as another entity
|
|
Entity *kdtree_vis = world->create();
|
|
kdtree_vis->assign<Lines>(collision_system->kdtree->get_lines());
|
|
|
|
Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs");
|
|
Shader shadowShader("Shaders/shadow-vertex.vs", "Shaders/shadow-fragment.fs");
|
|
Shader debugShader("Shaders/debug-vertex.vs", "Shaders/debug-fragment.fs");
|
|
Shader lineShader("Shaders/line-vertex.vs", "Shaders/line-fragment.fs");
|
|
|
|
double timeInLastFrame = glfwGetTime();
|
|
double elapsed_time = 0.0;
|
|
|
|
/* Loop until the user closes the window */
|
|
while (!glfwWindowShouldClose(window)) {
|
|
// Delta time handling
|
|
double delta = glfwGetTime() - timeInLastFrame;
|
|
timeInLastFrame = glfwGetTime();
|
|
elapsed_time += delta;
|
|
|
|
world->tick(delta);
|
|
renderSystem->render(world, defaultShader, shadowShader, debugShader, lineShader);
|
|
|
|
// Animations
|
|
/* ring->get<Transform>()->rotate(delta * 100.0, glm::vec3(0.0, 1.0, 0.0));
|
|
sun->get<DirectionalLight>()->direction = glm::normalize(glm::vec3(
|
|
glm::rotate(glm::mat4(1), (float)elapsed_time * 0.5f, glm::vec3(0.0, 1.0, 0.0))
|
|
* glm::vec4(1.0, 1.0, 1.0, 0.0))); */
|
|
|
|
// Swap front and back buffers
|
|
glfwSwapBuffers(window);
|
|
|
|
// Poll for and process events
|
|
glfwPollEvents();
|
|
}
|
|
|
|
glfwTerminate();
|
|
return 0;
|
|
}
|