Get ECS to a functional state

This commit is contained in:
Bailey Harrison 2023-01-02 17:24:20 +00:00
parent 2a7a9e54b2
commit e63e30fd4c
19 changed files with 451 additions and 391 deletions

View File

@ -9,50 +9,54 @@ project(engine LANGUAGES CXX
)
set(SRC_FILES
"src/ecs_system.cpp"
"src/application.cpp"
"src/window.cpp"
"src/input_manager.cpp"
"src/scene_manager.cpp"
"src/resources/texture.cpp"
"src/resources/material.cpp"
"src/gfx_device_vulkan.cpp"
"src/resources/texture.cpp"
"src/scene.cpp"
"src/gfx_device_vulkan.cpp"
"src/util/files.cpp"
"src/scene_manager.cpp"
"src/input_manager.cpp"
"src/window.cpp"
)
set(INCLUDE_FILES
"include/engine_api.h"
"include/application.hpp"
"include/util.hpp"
"include/log.hpp"
"include/logger.hpp"
"include/window.hpp"
"include/inputs/keyboard.hpp"
"include/inputs/mouse.hpp"
"include/input_manager.hpp"
"include/scene_manager.hpp"
"include/resource_manager.hpp"
"include/resources/material.hpp"
"include/resources/texture.hpp"
"include/resources/shader.hpp"
"include/resources/mesh.hpp"
"include/gfx.hpp"
"include/ecs_system.hpp"
"include/gfx_device.hpp"
"include/scene.hpp"
"include/ecs/ecs_system.hpp"
"include/ecs/transform.hpp"
"include/ecs/mesh_renderer.hpp"
"include/inputs/mouse.hpp"
"include/inputs/keyboard.hpp"
"include/input_manager.hpp"
"include/systems/transform.hpp"
"include/systems/render.hpp"
"include/resources/shader.hpp"
"include/resources/material.hpp"
"include/resources/mesh.hpp"
"include/resources/texture.hpp"
"include/engine_api.h"
"include/util/files.hpp"
"include/util.hpp"
"include/logger.hpp"
"include/scene_manager.hpp"
"include/gfx.hpp"
"include/scene.hpp"
"include/window.hpp"
"include/log.hpp"
"include/resource_manager.hpp"
"include/application.hpp"
"include/components/transform.hpp"
"include/components/renderable.hpp"
)
add_library(${PROJECT_NAME} STATIC

View File

@ -0,0 +1,12 @@
#pragma once
#include <glm/vec3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/mat4x4.hpp>
namespace engine {
struct RenderableComponent {
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <glm/vec3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/mat4x4.hpp>
#include <string>
namespace engine {
struct TransformComponent {
glm::vec3 position;
glm::quat rotation;
glm::vec3 scale;
glm::mat4 worldMatrix;
std::string tag;
uint32_t parent;
};
}

View File

@ -1,29 +0,0 @@
#pragma once
#include <map>
#include <memory>
namespace engine {
class Scene;
template <class T>
class EcsSystem {
public:
EcsSystem(Scene* scene)
: m_scene(scene)
{
}
~EcsSystem() {}
EcsSystem(const EcsSystem&) = delete;
EcsSystem& operator=(const EcsSystem&) = delete;
Scene* const m_scene;
std::map<uint32_t, T> m_components{};
};
}

View File

@ -1,105 +0,0 @@
#pragma once
#include "ecs_system.hpp"
#include "resources/material.hpp"
#include "resources/shader.hpp"
#include "resources/texture.hpp"
#include "resources/mesh.hpp"
#include "log.hpp"
#include "scene.hpp"
#include "application.hpp"
#include "window.hpp"
#include "gfx_device.hpp"
#include <glm/mat4x4.hpp>
#include <glm/gtc/quaternion.hpp>
#include <set>
namespace engine::ecs {
struct MeshRendererComponent {
std::shared_ptr<resources::Material> material;
std::shared_ptr<resources::Mesh> mesh;
};
class RendererSystem : public EcsSystem<MeshRendererComponent> {
public:
RendererSystem(Scene* scene)
: EcsSystem<MeshRendererComponent>(scene)
{
updateProjectionMatrix();
}
void drawMeshes(const std::map<uint32_t, glm::mat4>& worldTransforms)
{
glm::mat4 cameraTransform{1.0f};
// cameraTransform = glm::mat4_cast(m_cameraRot);
// reinterpret_cast<glm::vec3&>(cameraTransform[3]) = m_cameraPos;
glm::mat4 viewMatrix = glm::inverse(cameraTransform);
if (m_scene->app()->window()->getWindowResized()) {
updateProjectionMatrix();
}
std::set<resources::Shader*> uniqueShaders{};
for (const auto& [id, data] : m_components) {
uniqueShaders.insert(data.material->getShader());
}
for (resources::Shader* shader : uniqueShaders) {
DEBUG("TEST {}", (void*)shader);
m_scene->app()->gfx()->updateUniformBuffer(shader->getPipeline(), &m_projMatrix, sizeof(m_projMatrix), 0);
}
for (const auto& [id, data] : m_components) {
DEBUG("drawing entity {}", id);
DEBUG("material shader addr: {}", (void*)data.material->getShader());
assert(data.material != nullptr);
assert(data.mesh != nullptr);
struct {
glm::mat4 model;
glm::mat4 view;
} pushConsts{};
pushConsts.model = worldTransforms.at(id);
pushConsts.view = glm::mat4{1.0f};
m_scene->app()->gfx()->draw(
data.material->getShader()->getPipeline(),
data.mesh->getVB(),
data.mesh->getIB(),
data.mesh->getCount(),
&pushConsts, sizeof(pushConsts),
data.material->m_texture->getHandle());
}
}
glm::vec3 m_cameraPos;
glm::quat m_cameraRot;
glm::mat4 m_projMatrix;
private:
void updateProjectionMatrix()
{
constexpr float NEAR = 0.1f;
constexpr float FAR = 1000.0f;
float fovRad = glm::radians(75.0f);
uint32_t viewportWidth, viewportHeight;
m_scene->app()->gfx()->getViewportSize(&viewportWidth, &viewportHeight);
float aspect = (float)viewportWidth / (float)viewportHeight;
float fovY = fovRad / aspect;
m_projMatrix = glm::perspectiveZO(fovY, aspect, NEAR, FAR);
}
};
}

View File

@ -1,50 +0,0 @@
#pragma once
#include "ecs_system.hpp"
#include <glm/vec3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/mat4x4.hpp>
namespace engine::ecs {
struct TransformComponent {
uint32_t parent;
glm::vec3 scale;
glm::vec3 position;
glm::quat rotation;
};
class TransformSystem : public EcsSystem<TransformComponent> {
public:
TransformSystem(Scene* scene)
: EcsSystem<TransformComponent>(scene)
{
}
std::unique_ptr<std::map<uint32_t, glm::mat4>> getMatrices()
{
auto transforms = std::make_unique<std::map<uint32_t, glm::mat4>>();
for (const auto& [id, data] : m_components) {
glm::mat4 transform;
// rotation
transform = glm::mat4_cast(data.rotation);
// position
reinterpret_cast<glm::vec3&>(transform[3]) = data.position;
// scale (effectively applied first)
transform = glm::scale(transform, data.scale);
if (data.parent != 0) {
transform = transforms->at(data.parent) * transform;
}
transforms->emplace(id, transform);
}
return transforms;
}
};
}

67
include/ecs_system.hpp Normal file
View File

@ -0,0 +1,67 @@
#pragma once
#include <set>
#include <vector>
#include <map>
#include <string>
#include <bitset>
#include <cstdint>
#include <assert.h>
namespace engine {
class Scene;
constexpr size_t MAX_COMPONENTS = 64;
class IComponentArray {
public:
virtual ~IComponentArray() = default;
};
template<typename T>
class ComponentArray : public IComponentArray {
public:
void insertData(uint32_t entity, T component)
{
assert(m_componentArray.find(entity) == m_componentArray.end() && "Adding component which already exists to entity");
m_componentArray.emplace(entity, component);
}
void deleteData(uint32_t entity)
{
m_componentArray.erase(entity);
}
T* getData(uint32_t entity)
{
if (m_componentArray.contains(entity)) {
return &(m_componentArray.at(entity));
} else {
return nullptr;
}
}
std::map<uint32_t, T> m_componentArray{};
};
class System {
public:
System(Scene* scene, std::set<size_t> requiredComponentHashes);
~System() {}
System(const System&) = delete;
System& operator=(const System&) = delete;
virtual void onUpdate(float ts) = 0;
Scene* const m_scene;
std::bitset<MAX_COMPONENTS> m_signature;
std::set<uint32_t> m_entities{}; // entities that contain the required components
};
}

View File

@ -33,7 +33,7 @@ namespace engine {
sinks.emplace_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
#endif
auto logger = std::make_shared<spdlog::logger>("sdltest", sinks.begin(), sinks.end());
auto logger = std::make_shared<spdlog::logger>(appName, sinks.begin(), sinks.end());
logger->set_level(spdlog::level::trace);

View File

@ -12,9 +12,58 @@ namespace engine::resources {
class Shader {
public:
Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const gfx::VertexFormat& vertFormat, bool alphaBlending, bool cullBackFace)
// defines what vertex inputs are defined, position is always vec3
struct VertexParams {
bool hasNormal;
bool hasUV0;
bool hasUV1;
bool hasUV2;
bool hasUV3;
bool hasTangent;
bool hasColor;
};
Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
: m_gfx(gfx)
{
int index = 0;
uint32_t stride = 0;
gfx::VertexFormat vertFormat{};
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC3, stride);
stride += 3 * sizeof(float);
if (vertexParams.hasNormal) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC3, stride);
stride += 3 * sizeof(float);
}
if (vertexParams.hasUV0) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC2, stride);
stride += 2 * sizeof(float);
}
if (vertexParams.hasUV1) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC2, stride);
stride += 2 * sizeof(float);
}
if (vertexParams.hasUV2) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC2, stride);
stride += 2 * sizeof(float);
}
if (vertexParams.hasUV3) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC2, stride);
stride += 2 * sizeof(float);
}
if (vertexParams.hasTangent) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC3, stride);
stride += 3 * sizeof(float);
}
if (vertexParams.hasColor) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::VEC3, stride);
stride += 3 * sizeof(float);
}
vertFormat.stride = stride;
m_pipeline = m_gfx->createPipeline(vertPath, fragPath, vertFormat, sizeof(glm::mat4), alphaBlending, cullBackFace);
}
~Shader()

View File

@ -2,17 +2,17 @@
#include "log.hpp"
#include "ecs_system.hpp"
#include <map>
#include <cstdint>
#include <typeinfo>
#include <assert.h>
namespace engine {
class Application;
namespace ecs {
class TransformSystem;
class RendererSystem;
}
class Scene {
public:
@ -23,13 +23,79 @@ namespace engine {
void update(float ts);
uint32_t createEntity()
uint32_t createEntity(const std::string& tag, uint32_t parent = 0);
uint32_t getEntity(const std::string& tag, uint32_t parent = 0);
size_t getComponentSignaturePosition(size_t hash)
{
return m_nextEntityID++;
return m_componentSignaturePositions.at(hash);
}
std::unique_ptr<ecs::TransformSystem> m_transformSystem;
std::unique_ptr<ecs::RendererSystem> m_renderSystem;
template <typename T>
void registerComponent()
{
size_t hash = typeid(T).hash_code();
assert(m_componentArrays.contains(hash) == false && "Registering component type more than once.");
m_componentArrays.emplace(hash, std::make_unique<ComponentArray<T>>());
size_t componentSignaturePosition = m_nextSignaturePosition++;
assert(componentSignaturePosition < MAX_COMPONENTS && "Registering too many components!");
assert(m_componentSignaturePositions.contains(hash) == false);
m_componentSignaturePositions.emplace(hash, componentSignaturePosition);
}
template <typename T>
T* getComponent(uint32_t entity)
{
auto array = getComponentArray<T>();
return array->getData(entity);
}
template <typename T>
T* addComponent(uint32_t entity)
{
size_t hash = typeid(T).hash_code();
auto array = getComponentArray<T>();
array->insertData(entity, T{});
// set the component bit for this entity
size_t componentSignaturePosition = m_componentSignaturePositions.at(hash);
auto& signatureRef = m_signatures.at(entity);
signatureRef.set(componentSignaturePosition);
for (auto& [systemName, system] : m_systems)
{
if ((system->m_signature & signatureRef) == system->m_signature) {
system->m_entities.insert(entity);
}
}
return array->getData(entity);
}
template <typename T>
void registerSystem()
{
size_t hash = typeid(T).hash_code();
assert(m_systems.find(hash) == m_systems.end() && "Registering system more than once.");
m_systems.emplace(hash, std::make_unique<T>(this));
}
template <typename T>
T* getSystem()
{
size_t hash = typeid(T).hash_code();
auto it = m_systems.find(hash);
if (it == m_systems.end()) {
throw std::runtime_error("Cannot find ecs system.");
}
auto ptr = it->second.get();
auto castedPtr = dynamic_cast<T*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
}
Application* app() { return m_app; }
@ -37,6 +103,30 @@ namespace engine {
Application* const m_app;
uint32_t m_nextEntityID = 1000;
size_t m_nextSignaturePosition = 0;
// maps component hashes to signature positions
std::map<size_t, size_t> m_componentSignaturePositions{};
// maps entity ids to their signatures
std::map<uint32_t, std::bitset<MAX_COMPONENTS>> m_signatures{};
// maps component hashes to their arrays
std::map<size_t, std::unique_ptr<IComponentArray>> m_componentArrays{};
// maps system hashes to their class instantiations
std::map<size_t, std::unique_ptr<System>> m_systems{};
template <typename T>
ComponentArray<T>* getComponentArray()
{
size_t hash = typeid(T).hash_code();
auto it = m_componentArrays.find(hash);
if (it == m_componentArrays.end()) {
throw std::runtime_error("Cannot find component array.");
}
auto ptr = it->second.get();
auto castedPtr = dynamic_cast<ComponentArray<T>*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
}
};
}

View File

@ -11,6 +11,9 @@ namespace engine {
class Scene; // "scene.hpp"
namespace resources {
class Texture;
class Shader;
class Mesh;
class Material;
}
class SceneManager {
@ -21,21 +24,17 @@ namespace engine {
SceneManager(const SceneManager&) = delete;
SceneManager& operator=(const SceneManager&) = delete;
Scene* createScene();
// creates an empty scene and sets it as active
Scene* createEmptyScene();
void updateActiveScene(float ts);
/* getters */
ResourceManager<resources::Texture>* getTextureManager() { return m_textureManager.get(); }
private:
Application* const m_app;
std::vector<std::unique_ptr<Scene>> m_scenes;
int m_activeSceneIndex = -1;
std::unique_ptr<ResourceManager<resources::Texture>> m_textureManager;
};
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "ecs_system.hpp"
#include "scene.hpp"
#include "log.hpp"
#include "components/transform.hpp"
#include "components/renderable.hpp"
namespace engine {
class RenderSystem : public System {
public:
RenderSystem(Scene* scene)
: System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() })
{
}
void onUpdate(float ts) override
{
for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
TRACE("rendering {}", t->tag);
}
}
};
}

View File

@ -0,0 +1,67 @@
#pragma once
#include "ecs_system.hpp"
#include "components/transform.hpp"
#include "scene.hpp"
#include "log.hpp"
#include <glm/vec3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/mat4x4.hpp>
#include <typeinfo>
#include <string.h>
namespace engine {
class TransformSystem : public System {
public:
TransformSystem(Scene* scene)
: System(scene, { typeid(TransformComponent).hash_code() })
{
}
void onUpdate(float ts) override
{
for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
TRACE("tag is {}", t->tag);
glm::mat4 transform;
// rotation
transform = glm::mat4_cast(t->rotation);
// position
reinterpret_cast<glm::vec3&>(transform[3]) = t->position;
// scale (effectively applied first)
transform = glm::scale(transform, t->scale);
if (t->parent != 0) {
transform = m_scene->getComponent<TransformComponent>(t->parent)->worldMatrix * transform;
}
t->worldMatrix = transform;
}
}
uint32_t getChildEntity(uint32_t parent, const std::string& tag)
{
for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
if (t->parent == parent) {
if (t->tag == tag) {
return entity;
}
}
}
return 0;
}
};
}

16
src/ecs_system.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "ecs_system.hpp"
#include "scene.hpp"
namespace engine {
System::System(Scene* scene, std::set<size_t> requiredComponentHashes)
: m_scene(scene)
{
for (size_t componentHash : requiredComponentHashes) {
size_t componentSignaturePosition = m_scene->getComponentSignaturePosition(componentHash);
m_signature.set(componentSignaturePosition);
}
}
}

View File

@ -567,8 +567,6 @@ namespace engine {
swapchain->surfaceFormat = format; // prefer using srgb non linear colors
}
}
INFO("surface format: {}", swapchain->surfaceFormat.format);
INFO("surface colorspace: {}", swapchain->surfaceFormat.colorSpace);
swapchain->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available
if (vsync == false) {
@ -1244,18 +1242,14 @@ namespace engine {
VkQueueFamilyProperties family = queueFamilies[i];
if (family.queueCount > 0) {
if (graphicsFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
TRACE("GRAPHICS:");
graphicsFamilyIndex = i;
}
if (transferFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_TRANSFER_BIT) {
TRACE("TRANSFER:");
transferFamilyIndex = i;
}
if (computeFamilyIndex.has_value() == false && family.queueFlags & VK_QUEUE_COMPUTE_BIT) {
TRACE("COMPUTE:");
computeFamilyIndex = i;
}
TRACE("\t\ti = {}\t\tcount = {}", i, family.queueCount);
}
}
if (graphicsFamilyIndex.has_value() == false ||
@ -1288,7 +1282,6 @@ namespace engine {
if (transferFamilyIndex == family) newQueue.supportsTransfer = true;
if (computeFamilyIndex == family) newQueue.supportsCompute = true;
TRACE("Creating queue from family {}", family);
VkDeviceQueueCreateInfo queueCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
@ -1460,8 +1453,6 @@ namespace engine {
GFXDevice::~GFXDevice()
{
TRACE("Destroying GFXDevice...");
vkDestroyDescriptorSetLayout(pimpl->device, pimpl->samplerSetLayout, nullptr);
vkDestroyDescriptorSetLayout(pimpl->device, pimpl->descriptorSetLayout, nullptr);

View File

@ -1,24 +1,48 @@
#include "scene.hpp"
#include "ecs/transform.hpp"
#include "ecs/mesh_renderer.hpp"
#include "components/transform.hpp"
#include "components/renderable.hpp"
#include "systems/transform.hpp"
#include "systems/render.hpp"
namespace engine {
Scene::Scene(Application* app)
: m_app(app)
{
m_renderSystem = std::make_unique<ecs::RendererSystem>(this);
m_transformSystem = std::make_unique<ecs::TransformSystem>(this);
registerComponent<TransformComponent>();
registerComponent<RenderableComponent>();
registerSystem<TransformSystem>();
registerSystem<RenderSystem>();
}
Scene::~Scene() {}
uint32_t Scene::createEntity(const std::string& tag, uint32_t parent)
{
uint32_t id = m_nextEntityID++;
m_signatures.emplace(id, std::bitset<MAX_COMPONENTS>{});
auto t = addComponent<TransformComponent>(id);
t->tag = tag;
t->parent = parent;
return id;
}
uint32_t Scene::getEntity(const std::string& tag, uint32_t parent)
{
return getSystem<TransformSystem>()->getChildEntity(parent, tag);
}
void Scene::update(float ts)
{
auto transforms = m_transformSystem->getMatrices();
m_renderSystem->drawMeshes(*transforms);
for (auto& [name, system] : m_systems) {
system->onUpdate(ts);
}
}
}

View File

@ -10,12 +10,11 @@ namespace engine {
SceneManager::SceneManager(Application* app)
: m_app(app)
{
m_textureManager = std::make_unique<ResourceManager<resources::Texture>>();
}
SceneManager::~SceneManager() {}
Scene* SceneManager::createScene()
Scene* SceneManager::createEmptyScene()
{
auto scene = std::make_unique<Scene>(m_app);
m_scenes.emplace_back(std::move(scene));

View File

@ -1,92 +0,0 @@
#include "sceneroot.hpp"
#include "window.hpp"
#include "components/custom.hpp"
#include "components/camera.hpp"
#include "components/mesh_renderer.hpp"
#include "components/text_ui_renderer.hpp"
#include "gfx_device.hpp"
#include <glm/mat4x4.hpp>
#include <iostream>
#include <algorithm>
#include "log.hpp"
namespace engine {
SceneRoot::SceneRoot(struct GameIO things) : Object("root", nullptr, *this, things)
{
}
SceneRoot::~SceneRoot()
{
}
// private methods
// public methods
void SceneRoot::updateStuff()
{
using namespace components;
using namespace glm;
struct CompList compList {};
getAllSubComponents(compList, glm::mat4{ 1.0f });
// update
for (const auto& [c, t] : compList.customs) {
c->onUpdate(t);
}
// render
for (const auto& [c, camt] : compList.cameras) {
for (int id : m_activeCameras) {
if (c->getID() == id) {
glm::mat4 view{};
c->updateCam(camt, &view);
for (const auto& [ren, ren_t] : compList.renderers) {
ren->render(ren_t, view);
}
for (const auto& [textRen, textRen_t] : compList.uis) {
textRen->render(textRen_t, view);
}
break;
}
}
}
}
void SceneRoot::activateCam(int id)
{
auto& v = m_activeCameras;
if (std::find(v.begin(), v.end(), id) == v.end()) {
v.push_back(id);
}
}
void SceneRoot::deactivateCam(int id)
{
auto& v = m_activeCameras;
for (auto it = v.begin(); it != v.end(); it++) {
if (*it == id) {
v.erase(it);
}
}
}
}

View File

@ -4,65 +4,26 @@
#include "window.hpp"
#include "scene_manager.hpp"
#include "scene.hpp"
#include "resources/material.hpp"
#include "resources/shader.hpp"
#include "resources/texture.hpp"
#include "resources/mesh.hpp"
#include "ecs/transform.hpp"
#include "ecs/mesh_renderer.hpp"
#include "components/transform.hpp"
#include "components/renderable.hpp"
#include "systems/transform.hpp"
void playGame()
{
engine::Application app(PROJECT_NAME, PROJECT_VERSION);
// configure window
app.window()->setRelativeMouseMode(false);
app.window()->setRelativeMouseMode(true);
auto myScene = app.sceneManager()->createScene();
auto myScene = app.sceneManager()->createEmptyScene();
myScene->m_renderSystem->m_cameraPos = { 0.0f, 2.0f, 0.0f };
myScene->m_renderSystem->m_cameraRot = glm::angleAxis(0.0f, glm::vec3{ 0.0f, 0.0f, -1.0f });
myScene->createEntity("entity1");
{
auto entity1 = myScene->createEntity();
engine::gfx::VertexFormat vertFormat{};
vertFormat.stride = sizeof(float) * 8;
vertFormat.attributeDescriptions.emplace_back(0, engine::gfx::VertexAttribFormat::VEC3, 0);
vertFormat.attributeDescriptions.emplace_back(1, engine::gfx::VertexAttribFormat::VEC3, sizeof(float) * 3);
vertFormat.attributeDescriptions.emplace_back(2, engine::gfx::VertexAttribFormat::VEC2, sizeof(float) * 6);
auto myShader = std::make_unique<engine::resources::Shader>(
app.gfx(),
app.getResourcePath("engine/shaders/texture.vert").c_str(),
app.getResourcePath("engine/shaders/texture.frag").c_str(),
vertFormat,
false,
false
);
auto myMaterial = std::make_unique<engine::resources::Material>(std::move(myShader));
std::vector<engine::Vertex> triVertices{
{ { 0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f } },
{ { -0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f } },
};
myMaterial->m_texture = std::make_unique<engine::resources::Texture>(app.gfx(), app.getResourcePath("textures/grass.jpg"));
auto myMesh = std::make_unique<engine::resources::Mesh>(app.gfx(), triVertices);
myScene->m_renderSystem->m_components.emplace(
entity1,
engine::ecs::MeshRendererComponent{
std::move(myMaterial),
std::move(myMesh),
}
);
myScene->m_transformSystem->m_components.emplace(
entity1,
engine::ecs::TransformComponent{
.parent = 0,
.scale = {1.0f, 1.0f, 1.0f},
.position = {0.0f, 0.0f, -10.0f},
.rotation = glm::angleAxis(glm::radians(24.0f), glm::vec3{ 0.0f, 1.0f, 0.0f })
}
);
}
auto entity1 = myScene->getEntity("entity1");
myScene->getComponent<engine::TransformComponent>(entity1)->tag = "HELLO WORLD";
myScene->addComponent<engine::RenderableComponent>(entity1);
app.gameLoop();
}