diff --git a/debug.sh b/debug.sh new file mode 100755 index 0000000..23530fc --- /dev/null +++ b/debug.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +cd Debug +cmake --build . +cd test +./enginetest diff --git a/include/components/collider.hpp b/include/components/collider.hpp index b2985cb..cb3fa3f 100644 --- a/include/components/collider.hpp +++ b/include/components/collider.hpp @@ -5,38 +5,29 @@ namespace engine { - class PhysicsSystem; - - enum class ColliderType { - SPHERE, - PLANE, + struct AABB { + glm::vec3 pos1; + glm::vec3 pos2; }; + class PhysicsSystem; + struct ColliderComponent { friend PhysicsSystem; - ColliderType colliderType; + ColliderComponent() + { - union { - struct { - float r; - } sphereCollider; - } colliders; + } - auto getIsColliding() { return m_isColliding; } - auto getJustCollided() { return m_justCollided; } - auto getJustUncollided() { return m_justUncollided; } - auto getLastEntityCollided() { return m_lastEntityCollided; } - auto getLastCollisionNormal() { return m_lastCollisionNormal; } - auto getLastCollisionPoint() { return m_lastCollisionPoint; } + bool isStatic; + AABB aabb; + + glm::vec3 getLastCollisionNormal() { return {0.0f, 1.0f, 0.0f}; } + glm::vec3 getLastCollisionPoint() { return {}; } + bool getIsColliding() { return true; } + bool getJustUncollided() { return false; } - private: - bool m_isColliding; - bool m_justCollided; - bool m_justUncollided; - uint32_t m_lastEntityCollided; - glm::vec3 m_lastCollisionNormal; - glm::vec3 m_lastCollisionPoint; }; } diff --git a/include/ecs_system.hpp b/include/ecs_system.hpp index fa5bf91..8dbb7bb 100644 --- a/include/ecs_system.hpp +++ b/include/ecs_system.hpp @@ -43,6 +43,7 @@ namespace engine { } } + private: std::map m_componentArray{}; }; @@ -57,6 +58,9 @@ namespace engine { virtual void onUpdate(float ts) = 0; + virtual void onComponentInsert(uint32_t) {} + virtual void onComponentRemove(uint32_t) {} + Scene* const m_scene; std::bitset m_signature; diff --git a/include/logger.hpp b/include/logger.hpp index 3475908..497e1ee 100644 --- a/include/logger.hpp +++ b/include/logger.hpp @@ -28,14 +28,11 @@ namespace engine { sinks.emplace_back(std::make_shared(log_path.string(), true)); -#ifndef NDEBUG - // DEBUG sinks.emplace_back(std::make_shared()); -#endif auto logger = std::make_shared(appName, sinks.begin(), sinks.end()); - logger->set_level(spdlog::level::trace); + logger->set_level(spdlog::level::trace); // Logs below INFO are ignored through macros in release (see log.hpp) spdlog::register_logger(logger); spdlog::set_default_logger(logger); diff --git a/include/scene.hpp b/include/scene.hpp index 1a2d33e..73232fd 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -59,7 +59,7 @@ namespace engine { size_t hash = typeid(T).hash_code(); auto array = getComponentArray(); - array->insertData(entity, T{}); + array->insertData(entity, T{}); // errors if entity already exists in array // set the component bit for this entity size_t componentSignaturePosition = m_componentSignaturePositions.at(hash); @@ -68,8 +68,10 @@ namespace engine { for (auto& [systemName, system] : m_systems) { + if (system->m_entities.contains(entity)) continue; if ((system->m_signature & signatureRef) == system->m_signature) { system->m_entities.insert(entity); + system->onComponentInsert(entity); } } diff --git a/include/systems/collisions.hpp b/include/systems/collisions.hpp index e04d88f..5a2aed3 100644 --- a/include/systems/collisions.hpp +++ b/include/systems/collisions.hpp @@ -2,6 +2,10 @@ #include "ecs_system.hpp" +#include "components/collider.hpp" + +#include + namespace engine { class PhysicsSystem : public System { @@ -11,6 +15,21 @@ namespace engine { void onUpdate(float ts) override; + void onComponentInsert(uint32_t entity) override; + + private: + + // dyanmic arrays to avoid realloc on every frame + struct CollisionInfo { + uint32_t entity; + AABB aabb; + // output + bool isMaybeColliding; // broad phase + bool isColliding; // narrow phase + }; + std::vector m_staticInfos{}; + std::vector m_dynamicInfos{}; + }; } diff --git a/include/window.hpp b/include/window.hpp index 5d92a4a..13d3f3f 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -138,7 +138,7 @@ namespace engine { bool m_keyboardFocus = true; // size in screen coordinates - glm::ivec2 m_winSize = glm::vec2(640, 480); + glm::ivec2 m_winSize = glm::vec2(1024, 768); // performance counter frequency uint64_t m_counterFreq; diff --git a/prebuild.sh b/prebuild.sh new file mode 100755 index 0000000..d5c9b38 --- /dev/null +++ b/prebuild.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -e +mkdir -p Debug +cd Debug +cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug -D CMAKE_EXPORT_COMPILE_COMMANDS=ON .. +cd .. +mkdir -p Release +cd Release +cmake -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_EXPORT_COMPILE_COMMANDS=ON .. diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..7cf175e --- /dev/null +++ b/release.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +cd Release +cmake --build . +cd test +./enginetest diff --git a/res/engine/shaders/skybox.frag b/res/engine/shaders/skybox.frag new file mode 100644 index 0000000..a582a9a --- /dev/null +++ b/res/engine/shaders/skybox.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(location = 0) in vec2 fragUV; + +layout(location = 0) out vec4 outColor; + +layout(set = 1, binding = 0) uniform sampler2D texSampler; + +void main() { + + gl_FragDepth = 0.9999; + outColor = texture(texSampler, fragUV); + +} + diff --git a/res/engine/shaders/skybox.vert b/res/engine/shaders/skybox.vert new file mode 100644 index 0000000..210fad8 --- /dev/null +++ b/res/engine/shaders/skybox.vert @@ -0,0 +1,24 @@ +#version 450 + +layout(binding = 0) uniform UBO { + mat4 proj; +} ubo; + +layout( push_constant ) uniform Constants { + mat4 model; + mat4 view; +} constants; + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNorm; +layout(location = 2) in vec2 inUV; + +layout(location = 0) out vec2 fragUV; + +void main() { + mat4 myView = constants.view; + myView[3] = vec4(0.0, 0.0, 0.0, 1.0); + vec4 pos = ubo.proj * myView * constants.model * vec4(inPosition, 1.0); + gl_Position = pos; + fragUV = inUV; +} diff --git a/run.sh b/run.sh deleted file mode 100755 index f1b72b7..0000000 --- a/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd "Debug/test" -./enginetest diff --git a/src/application.cpp b/src/application.cpp index 609a46d..c0c4ad0 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -87,6 +87,20 @@ namespace engine { ); getResourceManager()->addPersistent("engine.textured", std::move(texturedShader)); } + { + resources::Shader::VertexParams vertParams{}; + vertParams.hasNormal = true; + vertParams.hasUV0 = true; + auto texturedShader = std::make_unique( + gfx(), + getResourcePath("engine/shaders/skybox.vert").c_str(), + getResourcePath("engine/shaders/skybox.frag").c_str(), + vertParams, + false, + true + ); + getResourceManager()->addPersistent("engine.skybox", std::move(texturedShader)); + } { auto whiteTexture = std::make_unique( gfx(), diff --git a/src/scene.cpp b/src/scene.cpp index 4a61b92..439794f 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -22,7 +22,13 @@ namespace engine { registerSystem(); } - Scene::~Scene() {} + Scene::~Scene() + { + INFO("Entity signatures:"); + for (auto [entity, signature] : m_signatures) { + INFO("entity {}, signature: {}", entity, signature.to_string()); + } + } uint32_t Scene::createEntity(const std::string& tag, uint32_t parent) { @@ -54,7 +60,6 @@ namespace engine { void Scene::update(float ts) { - for (auto& [name, system] : m_systems) { system->onUpdate(ts); } diff --git a/src/systems/collisions.cpp b/src/systems/collisions.cpp index 5c82096..8e2e975 100644 --- a/src/systems/collisions.cpp +++ b/src/systems/collisions.cpp @@ -9,128 +9,96 @@ namespace engine { + // static functions + + static bool checkCollisionFast(AABB a, AABB b) + { + if (a.pos1.x > a.pos2.x) std::swap(a.pos1.x, a.pos2.x); + if (a.pos1.y > a.pos2.y) std::swap(a.pos1.y, a.pos2.y); + if (a.pos1.z > a.pos2.z) std::swap(a.pos1.z, a.pos2.z); + if (b.pos1.x > b.pos2.x) std::swap(b.pos1.x, b.pos2.x); + if (b.pos1.y > b.pos2.y) std::swap(b.pos1.y, b.pos2.y); + if (b.pos1.z > b.pos2.z) std::swap(b.pos1.z, b.pos2.z); + + return ( + a.pos1.x <= b.pos2.x && + a.pos2.x >= b.pos1.x && + a.pos1.y <= b.pos2.y && + a.pos2.y >= b.pos1.y && + a.pos1.z <= b.pos2.z && + a.pos2.z >= b.pos1.z + ); + } + + // class methods + PhysicsSystem::PhysicsSystem(Scene* scene) : System(scene, { typeid(TransformComponent).hash_code(), typeid(ColliderComponent).hash_code() }) { + } + void PhysicsSystem::onComponentInsert(uint32_t entity) + { + (void)entity; + m_staticInfos.reserve(m_entities.size()); + m_dynamicInfos.reserve(m_entities.size()); + TRACE("added entity {} to collider system", entity); } void PhysicsSystem::onUpdate(float ts) { (void)ts; - using glm::vec3; + m_staticInfos.clear(); + m_dynamicInfos.clear(); - struct CollisionInfo { - uint32_t entity; - TransformComponent* t; - ColliderComponent* c; + TRACE("Getting collider entities:"); + for (uint32_t entity : m_entities) { + TRACE(" has entity: {}", entity); + const auto t = m_scene->getComponent(entity); + const auto c = m_scene->getComponent(entity); - vec3 pos; + const glm::vec3 globalPosition = t->worldMatrix[3]; + const AABB localBoundingBox = c->aabb; + AABB globalBoundingBox; + globalBoundingBox.pos1 = globalPosition + localBoundingBox.pos1; + globalBoundingBox.pos2 = globalPosition + localBoundingBox.pos2; + TRACE(" global bounding box:"); + TRACE(" pos1: {} {} {}", globalBoundingBox.pos1.x, globalBoundingBox.pos1.y, globalBoundingBox.pos1.z); + TRACE(" pos2: {} {} {}", globalBoundingBox.pos2.x, globalBoundingBox.pos2.y, globalBoundingBox.pos2.z); + + CollisionInfo info{ + .entity = entity, + .aabb = globalBoundingBox, + .isMaybeColliding = false, + .isColliding = false + }; + if (c->isStatic) { + m_staticInfos.push_back(info); + } else { + m_dynamicInfos.push_back(info); + } + } + + /* BROAD PHASE */ + + TRACE("Starting broad phase collision test"); + + struct PossibleCollision { - bool wasColliding; }; - std::vector entityColliders(m_entities.size()); - - uint32_t i = 0; - for (uint32_t entity : m_entities) { - auto t = m_scene->getComponent(entity); - auto c = m_scene->getComponent(entity); - - entityColliders[i].entity = entity; - entityColliders[i].t = t; - entityColliders[i].c = c; - - entityColliders[i].wasColliding = c->getIsColliding(); - c->m_isColliding = false; - c->m_justCollided = false; - c->m_justUncollided = false; - - vec3 pos = reinterpret_cast(t->worldMatrix[3]); - entityColliders[i].pos = pos; - - i++; + // Check every static collider against every dynamic collider, and every dynamic collider against every other one + // This technique is inefficient for many entities. + for (size_t i = 0; i < m_staticInfos.size(); i++) { + for (size_t j = 0; j < m_dynamicInfos.size(); j++) { + if (checkCollisionFast(m_staticInfos[i].aabb, m_dynamicInfos[j].aabb)) { + m_staticInfos[i].isMaybeColliding = true; + m_dynamicInfos[i].isMaybeColliding = true; + TRACE("Collision detected between {} and {}", m_staticInfos[i].entity, m_dynamicInfos[j].entity); + } + } } - - // compares every entity to every other entity, but pairs are never repeated - for (size_t i = 0; i < entityColliders.size(); i++) { - auto* ec1 = &entityColliders[i]; - - for (size_t j = i + 1; j < entityColliders.size(); j++) { - - auto* ec2 = &entityColliders[j]; - - if ( ec1->c->colliderType == ColliderType::SPHERE && - ec2->c->colliderType == ColliderType::SPHERE ) { - const vec3 v = ec2->pos - ec1->pos; - const float distanceSquared = v.x * v.x + v.y * v.y + v.z * v.z; - const float sumOfRadii = ec1->c->colliders.sphereCollider.r + ec2->c->colliders.sphereCollider.r; - const float sumOfRadiiSquared = sumOfRadii * sumOfRadii; - if (distanceSquared < sumOfRadiiSquared) { - ec1->c->m_isColliding = true; - ec1->c->m_lastEntityCollided = ec2->entity; - ec1->c->m_lastCollisionNormal = glm::normalize(v); - ec1->c->m_lastCollisionPoint = ec1->pos + (v * ec1->c->colliders.sphereCollider.r / glm::sqrt(distanceSquared)); - ec2->c->m_isColliding = true; - ec2->c->m_lastEntityCollided = ec1->entity; - ec2->c->m_lastCollisionNormal = -ec1->c->m_lastCollisionNormal; - ec2->c->m_lastCollisionPoint = ec1->c->m_lastCollisionPoint; - } - } else if ( (ec1->c->colliderType == ColliderType::PLANE && - ec2->c->colliderType == ColliderType::SPHERE) || - (ec1->c->colliderType == ColliderType::SPHERE && - ec2->c->colliderType == ColliderType::PLANE)) { - CollisionInfo *plane, *sphere; - if (ec1->c->colliderType == ColliderType::PLANE) { - plane = ec1; - sphere = ec2; - } else { - sphere = ec1; - plane = ec2; - } - float distance = plane->pos.y - sphere->pos.y; - if (distance < 0.0f) distance = -distance; // make positive - if (distance < sphere->c->colliders.sphereCollider.r) { - plane->c->m_isColliding = true; - plane->c->m_lastEntityCollided = sphere->entity; - plane->c->m_lastCollisionNormal = {0.0f, -1.0f, 0.0f}; - plane->c->m_lastCollisionPoint = {sphere->pos.x, plane->pos.y, sphere->pos.z}; - sphere->c->m_isColliding = true; - sphere->c->m_lastEntityCollided = plane->entity; - sphere->c->m_lastCollisionNormal = {0.0f, 1.0f, 0.0f}; - sphere->c->m_lastCollisionPoint = plane->c->m_lastCollisionPoint; - } - } else { - throw std::runtime_error("Collision combination not supported!"); - } - - } - - if (ec1->wasColliding != ec1->c->getIsColliding()) { - if (ec1->c->getIsColliding()) { - ec1->c->m_justCollided = true; - } else { - ec1->c->m_justUncollided = true; - } - } - if (ec1->c->getJustCollided()) { - TRACE("'{}' has collided!", ec1->t->tag); - auto r = m_scene->getComponent(ec1->entity); - if (r != nullptr) { - r->shown = true; - } - } - if (ec1->c->getJustUncollided()) { - TRACE("'{}' has stopped colliding!", ec1->t->tag); - auto r = m_scene->getComponent(ec1->entity); - if (r != nullptr) { - r->shown = false; - } - } - - } - } } diff --git a/src/util/files.cpp b/src/util/files.cpp index 4b203b3..9254560 100644 --- a/src/util/files.cpp +++ b/src/util/files.cpp @@ -51,7 +51,7 @@ namespace engine::util { return buffer; } - // returns false if unable to open file + // Read an image file into a vector byte buffer. PNG and JPG support at a minimum std::unique_ptr> readImageFile(const std::string& path, int *width, int *height) { int x, y, n; diff --git a/test/res/textures/space.jpg b/test/res/textures/space.jpg new file mode 100644 index 0000000..7d1e8d3 Binary files /dev/null and b/test/res/textures/space.jpg differ diff --git a/test/res/textures/space2.png b/test/res/textures/space2.png new file mode 100644 index 0000000..159405f Binary files /dev/null and b/test/res/textures/space2.png differ diff --git a/test/src/camera_controller.cpp b/test/src/camera_controller.cpp index 250fa0f..001d50b 100644 --- a/test/src/camera_controller.cpp +++ b/test/src/camera_controller.cpp @@ -42,6 +42,7 @@ void CameraControllerSystem::onUpdate(float ts) const float dt = ts; +/* constexpr float G = 9.8f; // constexpr float MAX_SLOPE_ANGLE = glm::radians(20.0f); constexpr float MAX_SLOPE_ANGLE = glm::radians(1000.0f); // treat every collider as a floor, (TODO: get wall collisions working so this can be removed) @@ -89,11 +90,15 @@ void CameraControllerSystem::onUpdate(float ts) c->dy += dt * c->thrust; } +*/ + // in metres per second - //constexpr float SPEED = 1.5f; float SPEED = c->walk_speed; if (m_scene->app()->inputManager()->getButton("sprint")) SPEED *= 10.0f; + if (m_scene->app()->inputManager()->getButton("fire")) t->position.y += dt * SPEED; + if (m_scene->app()->inputManager()->getButton("aim")) t->position.y -= dt * SPEED; + float dx = m_scene->app()->inputManager()->getAxis("movex"); float dz = (-m_scene->app()->inputManager()->getAxis("movey")); @@ -113,9 +118,10 @@ void CameraControllerSystem::onUpdate(float ts) const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, c->m_yaw); const glm::vec3 d2zRotated = glm::rotateY(glm::vec3{ 0.0f, 0.0f, dz }, c->m_yaw); glm::vec3 hVel = (d2xRotated + d2zRotated); - if (isSliding) { +/* if (isSliding) { hVel = glm::vec3{norm.z, 0.0f, -norm.x}; } +*/ hVel *= SPEED; t->position += hVel * dt; t->position.y += c->dy * dt; @@ -158,8 +164,7 @@ void CameraControllerSystem::onUpdate(float ts) " y: " + std::to_string(t->position.y) + " z: " + std::to_string(t->position.z) }; -// m_scene->app()->window()->infoBox("POSITION", pos_string); - m_scene->app()->window()->infoBox("POSITION", std::to_string(slope)); + m_scene->app()->window()->infoBox("POSITION", pos_string); INFO("position: " + pos_string); } diff --git a/test/src/game.cpp b/test/src/game.cpp index 239ec22..2f4a2a7 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -42,7 +42,7 @@ void playGame() { engine::Application app(PROJECT_NAME, PROJECT_VERSION); - app.setFrameLimiter(true); + app.setFrameLimiter(false); // configure window app.window()->setRelativeMouseMode(true); @@ -51,20 +51,22 @@ void playGame() auto myScene = app.sceneManager()->createEmptyScene(); - myScene->registerComponent(); - myScene->registerSystem(); + /* create camera */ + { + myScene->registerComponent(); + myScene->registerSystem(); - auto camera = myScene->createEntity("camera"); - myScene->getComponent(camera)->position.y = 8.0f; - auto cameraCollider = myScene->addComponent(camera); - cameraCollider->colliderType = engine::ColliderType::SPHERE; - cameraCollider->colliders.sphereCollider.r = 1.8f; - myScene->addComponent(camera); + auto camera = myScene->createEntity("camera"); + myScene->getComponent(camera)->position.y = 8.0f; + auto cameraCollider = myScene->addComponent(camera); + cameraCollider->isStatic = false; + cameraCollider->aabb = { { -0.2f, -1.5f, -0.2f }, { 0.2f, 0.2f, 0.2f} }; // Origin is at eye level + myScene->addComponent(camera); - myScene->getSystem()->setCameraEntity(camera); - -// engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/van/van.dae")); + myScene->getSystem()->setCameraEntity(camera); + } + /* shared resources */ auto grassTexture = std::make_shared( app.gfx(), app.getResourcePath("textures/grass.jpg"), @@ -72,39 +74,53 @@ void playGame() true, true ); + auto spaceTexture = std::make_shared( + app.gfx(), + app.getResourcePath("textures/space2.png"), + engine::resources::Texture::Filtering::ANISOTROPIC, + true, + true + ); - uint32_t enemy = myScene->createEntity("enemy"); - auto enemyRenderable = myScene->addComponent(enemy); - enemyRenderable->material = std::make_unique(app.getResource("engine.textured")); - enemyRenderable->material->m_texture = app.getResource("engine.white"); - enemyRenderable->mesh = genSphereMesh(app.gfx(), 5.0f, 50, false); - auto enemyT = myScene->getComponent(enemy); - enemyT->position.x += 10.0f; - enemyT->position.y += 2.0f; - enemyT->position.z += 14.0f; - auto enemyCollider = myScene->addComponent(enemy); - enemyCollider->colliderType = engine::ColliderType::SPHERE; - enemyCollider->colliders.sphereCollider.r = 5.0f; + /* skybox */ + { + uint32_t skybox = myScene->createEntity("skybox"); + auto skyboxRenderable = myScene->addComponent(skybox); + skyboxRenderable->material = std::make_unique(app.getResource("engine.skybox")); + skyboxRenderable->material->m_texture = spaceTexture; +// skyboxRenderable->mesh = genSphereMesh(app.gfx(), 1.0f, 50, true); + skyboxRenderable->mesh = genCuboidMesh(app.gfx(), 2.0f, 2.0f, 2.0f, 1.0f, true); + myScene->getComponent(skybox)->position = { -1.0f, -1.0f, -1.0f }; + } - uint32_t sphere = myScene->createEntity("sphere"); - auto sphereRenderable = myScene->addComponent(sphere); - sphereRenderable->material = std::make_unique(app.getResource("engine.textured")); - sphereRenderable->material->m_texture = app.getResource("engine.white"); - sphereRenderable->mesh = genSphereMesh(app.gfx(), 100.0f, 50, true); + /* enemy sphere */ + { + uint32_t enemy = myScene->createEntity("enemy"); + auto enemyRenderable = myScene->addComponent(enemy); + enemyRenderable->material = std::make_unique(app.getResource("engine.textured")); + enemyRenderable->material->m_texture = app.getResource("engine.white"); + enemyRenderable->mesh = genSphereMesh(app.gfx(), 5.0f, 50, false); + auto enemyTransform = myScene->getComponent(enemy); + enemyTransform->position.x = 10.0f; + enemyTransform->position.y = 0.0f; + enemyTransform->position.z = 14.0f; + auto enemyCollider = myScene->addComponent(enemy); + enemyCollider->isStatic = true; + enemyCollider->aabb = { { -5.0f, -5.0f, -5.0f }, { 5.0f, 5.0f, 5.0f } }; // A box enclosing the sphere + } - uint32_t light = myScene->createEntity("light"); - myScene->getComponent(light)->position = glm::vec3{-10.0f, 10.0f, 10.0f}; - auto lightRenderable = myScene->addComponent(light); - lightRenderable->material = sphereRenderable->material; - lightRenderable->mesh = genSphereMesh(app.gfx(), 0.5f, 40, false, true); - - uint32_t floor = myScene->createEntity("floor"); - myScene->getComponent(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f}; - auto floorRenderable = myScene->addComponent(floor); - floorRenderable->material = std::make_shared(*sphereRenderable->material); - floorRenderable->material->m_texture = grassTexture; - floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f); - myScene->addComponent(floor)->colliderType = engine::ColliderType::PLANE; + /* floor */ + { + uint32_t floor = myScene->createEntity("floor"); + myScene->getComponent(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f}; + auto floorRenderable = myScene->addComponent(floor); + floorRenderable->material = std::make_shared(app.getResource("engine.textured")); + floorRenderable->material->m_texture = grassTexture; + floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f, 128.0f); + auto floorCollider = myScene->addComponent(floor); + floorCollider->isStatic = true; + floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 100.0f, 0.1f, 100.0f } }; + } app.gameLoop(); diff --git a/test/src/meshgen.cpp b/test/src/meshgen.cpp index 0eff00b..05baa08 100644 --- a/test/src/meshgen.cpp +++ b/test/src/meshgen.cpp @@ -88,7 +88,7 @@ std::unique_ptr genSphereMesh(engine::GFXDevice* gfx, f return std::make_unique(gfx, vertices); } -std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z) +std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling, bool windInside) { // x goes -> @@ -99,8 +99,6 @@ std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, f std::vector v{}; - const float tiling = 128.0f; - // front v.push_back({{x, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {tiling, 0.0f}}); v.push_back({{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f}}); @@ -149,6 +147,12 @@ std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, f v.push_back({{0.0f, y, z}, {0.0f, 1.0f, 0.0f}, {0.0f, tiling}}); v.push_back({{x, y, z}, {0.0f, 1.0f, 0.0f}, {tiling, tiling}}); + if (windInside) { + for (size_t i = 0; i < v.size(); i += 3) { + std::swap(v[i], v[i + 2]); + } + } + return std::make_unique(gfx, v); } diff --git a/test/src/meshgen.hpp b/test/src/meshgen.hpp index 65335b4..98e011c 100644 --- a/test/src/meshgen.hpp +++ b/test/src/meshgen.hpp @@ -5,4 +5,4 @@ // generates a UV sphere std::unique_ptr genSphereMesh(engine::GFXDevice* gfx, float r, int detail, bool windInside = false, bool flipNormals = false); -std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z); +std::unique_ptr genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling = 1.0f, bool windInside = false);