mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Begin collision rewrite
This commit is contained in:
parent
ca02bf6084
commit
bb7d70e79e
6
debug.sh
Executable file
6
debug.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
cd Debug
|
||||
cmake --build .
|
||||
cd test
|
||||
./enginetest
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ namespace engine {
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<uint32_t, T> 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<MAX_COMPONENTS> m_signature;
|
||||
|
@ -28,14 +28,11 @@ namespace engine {
|
||||
|
||||
sinks.emplace_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_path.string(), true));
|
||||
|
||||
#ifndef NDEBUG
|
||||
// DEBUG
|
||||
sinks.emplace_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
|
||||
#endif
|
||||
|
||||
auto logger = std::make_shared<spdlog::logger>(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);
|
||||
|
@ -59,7 +59,7 @@ namespace engine {
|
||||
size_t hash = typeid(T).hash_code();
|
||||
|
||||
auto array = getComponentArray<T>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
#include "ecs_system.hpp"
|
||||
|
||||
#include "components/collider.hpp"
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
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<CollisionInfo> m_staticInfos{};
|
||||
std::vector<CollisionInfo> m_dynamicInfos{};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
9
prebuild.sh
Executable file
9
prebuild.sh
Executable file
@ -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 ..
|
6
release.sh
Executable file
6
release.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
cd Release
|
||||
cmake --build .
|
||||
cd test
|
||||
./enginetest
|
15
res/engine/shaders/skybox.frag
Normal file
15
res/engine/shaders/skybox.frag
Normal file
@ -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);
|
||||
|
||||
}
|
||||
|
24
res/engine/shaders/skybox.vert
Normal file
24
res/engine/shaders/skybox.vert
Normal file
@ -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;
|
||||
}
|
@ -87,6 +87,20 @@ namespace engine {
|
||||
);
|
||||
getResourceManager<resources::Shader>()->addPersistent("engine.textured", std::move(texturedShader));
|
||||
}
|
||||
{
|
||||
resources::Shader::VertexParams vertParams{};
|
||||
vertParams.hasNormal = true;
|
||||
vertParams.hasUV0 = true;
|
||||
auto texturedShader = std::make_unique<resources::Shader>(
|
||||
gfx(),
|
||||
getResourcePath("engine/shaders/skybox.vert").c_str(),
|
||||
getResourcePath("engine/shaders/skybox.frag").c_str(),
|
||||
vertParams,
|
||||
false,
|
||||
true
|
||||
);
|
||||
getResourceManager<resources::Shader>()->addPersistent("engine.skybox", std::move(texturedShader));
|
||||
}
|
||||
{
|
||||
auto whiteTexture = std::make_unique<resources::Texture>(
|
||||
gfx(),
|
||||
|
@ -22,7 +22,13 @@ namespace engine {
|
||||
registerSystem<RenderSystem>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -9,129 +9,97 @@
|
||||
|
||||
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<TransformComponent>(entity);
|
||||
const auto c = m_scene->getComponent<ColliderComponent>(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<CollisionInfo> entityColliders(m_entities.size());
|
||||
|
||||
uint32_t i = 0;
|
||||
for (uint32_t entity : m_entities) {
|
||||
auto t = m_scene->getComponent<TransformComponent>(entity);
|
||||
auto c = m_scene->getComponent<ColliderComponent>(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<vec3&>(t->worldMatrix[3]);
|
||||
entityColliders[i].pos = pos;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
if (ec1->c->getJustCollided()) {
|
||||
TRACE("'{}' has collided!", ec1->t->tag);
|
||||
auto r = m_scene->getComponent<RenderableComponent>(ec1->entity);
|
||||
if (r != nullptr) {
|
||||
r->shown = true;
|
||||
}
|
||||
}
|
||||
if (ec1->c->getJustUncollided()) {
|
||||
TRACE("'{}' has stopped colliding!", ec1->t->tag);
|
||||
auto r = m_scene->getComponent<RenderableComponent>(ec1->entity);
|
||||
if (r != nullptr) {
|
||||
r->shown = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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<std::vector<uint8_t>> readImageFile(const std::string& path, int *width, int *height)
|
||||
{
|
||||
int x, y, n;
|
||||
|
BIN
test/res/textures/space.jpg
Normal file
BIN
test/res/textures/space.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 415 KiB |
BIN
test/res/textures/space2.png
Normal file
BIN
test/res/textures/space2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
/* create camera */
|
||||
{
|
||||
myScene->registerComponent<CameraControllerComponent>();
|
||||
myScene->registerSystem<CameraControllerSystem>();
|
||||
|
||||
auto camera = myScene->createEntity("camera");
|
||||
myScene->getComponent<engine::TransformComponent>(camera)->position.y = 8.0f;
|
||||
auto cameraCollider = myScene->addComponent<engine::ColliderComponent>(camera);
|
||||
cameraCollider->colliderType = engine::ColliderType::SPHERE;
|
||||
cameraCollider->colliders.sphereCollider.r = 1.8f;
|
||||
cameraCollider->isStatic = false;
|
||||
cameraCollider->aabb = { { -0.2f, -1.5f, -0.2f }, { 0.2f, 0.2f, 0.2f} }; // Origin is at eye level
|
||||
myScene->addComponent<CameraControllerComponent>(camera);
|
||||
|
||||
myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera);
|
||||
}
|
||||
|
||||
// engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/van/van.dae"));
|
||||
|
||||
/* shared resources */
|
||||
auto grassTexture = std::make_shared<engine::resources::Texture>(
|
||||
app.gfx(),
|
||||
app.getResourcePath("textures/grass.jpg"),
|
||||
@ -72,39 +74,53 @@ void playGame()
|
||||
true,
|
||||
true
|
||||
);
|
||||
auto spaceTexture = std::make_shared<engine::resources::Texture>(
|
||||
app.gfx(),
|
||||
app.getResourcePath("textures/space2.png"),
|
||||
engine::resources::Texture::Filtering::ANISOTROPIC,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
/* skybox */
|
||||
{
|
||||
uint32_t skybox = myScene->createEntity("skybox");
|
||||
auto skyboxRenderable = myScene->addComponent<engine::RenderableComponent>(skybox);
|
||||
skyboxRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("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<engine::TransformComponent>(skybox)->position = { -1.0f, -1.0f, -1.0f };
|
||||
}
|
||||
|
||||
/* enemy sphere */
|
||||
{
|
||||
uint32_t enemy = myScene->createEntity("enemy");
|
||||
auto enemyRenderable = myScene->addComponent<engine::RenderableComponent>(enemy);
|
||||
enemyRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.textured"));
|
||||
enemyRenderable->material->m_texture = app.getResource<engine::resources::Texture>("engine.white");
|
||||
enemyRenderable->mesh = genSphereMesh(app.gfx(), 5.0f, 50, false);
|
||||
auto enemyT = myScene->getComponent<engine::TransformComponent>(enemy);
|
||||
enemyT->position.x += 10.0f;
|
||||
enemyT->position.y += 2.0f;
|
||||
enemyT->position.z += 14.0f;
|
||||
auto enemyTransform = myScene->getComponent<engine::TransformComponent>(enemy);
|
||||
enemyTransform->position.x = 10.0f;
|
||||
enemyTransform->position.y = 0.0f;
|
||||
enemyTransform->position.z = 14.0f;
|
||||
auto enemyCollider = myScene->addComponent<engine::ColliderComponent>(enemy);
|
||||
enemyCollider->colliderType = engine::ColliderType::SPHERE;
|
||||
enemyCollider->colliders.sphereCollider.r = 5.0f;
|
||||
|
||||
uint32_t sphere = myScene->createEntity("sphere");
|
||||
auto sphereRenderable = myScene->addComponent<engine::RenderableComponent>(sphere);
|
||||
sphereRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.textured"));
|
||||
sphereRenderable->material->m_texture = app.getResource<engine::resources::Texture>("engine.white");
|
||||
sphereRenderable->mesh = genSphereMesh(app.gfx(), 100.0f, 50, true);
|
||||
|
||||
uint32_t light = myScene->createEntity("light");
|
||||
myScene->getComponent<engine::TransformComponent>(light)->position = glm::vec3{-10.0f, 10.0f, 10.0f};
|
||||
auto lightRenderable = myScene->addComponent<engine::RenderableComponent>(light);
|
||||
lightRenderable->material = sphereRenderable->material;
|
||||
lightRenderable->mesh = genSphereMesh(app.gfx(), 0.5f, 40, false, true);
|
||||
enemyCollider->isStatic = true;
|
||||
enemyCollider->aabb = { { -5.0f, -5.0f, -5.0f }, { 5.0f, 5.0f, 5.0f } }; // A box enclosing the sphere
|
||||
}
|
||||
|
||||
/* floor */
|
||||
{
|
||||
uint32_t floor = myScene->createEntity("floor");
|
||||
myScene->getComponent<engine::TransformComponent>(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f};
|
||||
auto floorRenderable = myScene->addComponent<engine::RenderableComponent>(floor);
|
||||
floorRenderable->material = std::make_shared<engine::resources::Material>(*sphereRenderable->material);
|
||||
floorRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.textured"));
|
||||
floorRenderable->material->m_texture = grassTexture;
|
||||
floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f);
|
||||
myScene->addComponent<engine::ColliderComponent>(floor)->colliderType = engine::ColliderType::PLANE;
|
||||
floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f, 128.0f);
|
||||
auto floorCollider = myScene->addComponent<engine::ColliderComponent>(floor);
|
||||
floorCollider->isStatic = true;
|
||||
floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 100.0f, 0.1f, 100.0f } };
|
||||
}
|
||||
|
||||
app.gameLoop();
|
||||
|
||||
|
@ -88,7 +88,7 @@ std::unique_ptr<engine::resources::Mesh> genSphereMesh(engine::GFXDevice* gfx, f
|
||||
return std::make_unique<engine::resources::Mesh>(gfx, vertices);
|
||||
}
|
||||
|
||||
std::unique_ptr<engine::resources::Mesh> genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z)
|
||||
std::unique_ptr<engine::resources::Mesh> genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling, bool windInside)
|
||||
{
|
||||
|
||||
// x goes ->
|
||||
@ -99,8 +99,6 @@ std::unique_ptr<engine::resources::Mesh> genCuboidMesh(engine::GFXDevice* gfx, f
|
||||
|
||||
std::vector<engine::Vertex> 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<engine::resources::Mesh> 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<engine::resources::Mesh>(gfx, v);
|
||||
|
||||
}
|
||||
|
@ -5,4 +5,4 @@
|
||||
|
||||
// generates a UV sphere
|
||||
std::unique_ptr<engine::resources::Mesh> genSphereMesh(engine::GFXDevice* gfx, float r, int detail, bool windInside = false, bool flipNormals = false);
|
||||
std::unique_ptr<engine::resources::Mesh> genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z);
|
||||
std::unique_ptr<engine::resources::Mesh> genCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling = 1.0f, bool windInside = false);
|
||||
|
Loading…
Reference in New Issue
Block a user