#include "Lightkeeper.h" #include #include "glm/gtx/transform.hpp" #include "spdlog/spdlog.h" #include #include "destrum/Components/MeshRendererComponent.h" #include "destrum/Components/Rotator.h" #include "destrum/Components/Spinner.h" #include "destrum/Components/OrbitAndSpin.h" #include "destrum/ObjectModel/GameObject.h" #include "destrum/Util/ModelLoader.h" #include "destrum/Components/Animator.h" LightKeeper::LightKeeper(): App(), renderer(meshCache, materialCache) { } LightKeeper::~LightKeeper() { } void LightKeeper::customInit() { materialCache.init(gfxDevice); renderer.init(gfxDevice, m_params.renderSize); const float aspectRatio = static_cast(m_params.renderSize.x) / static_cast(m_params.renderSize.y); camera.setAspectRatio(aspectRatio); // // testMesh.name = "Test Mesh"; // auto list_of_models = ModelLoader::LoadGLTF_CPUMeshes_MergedPerMesh(AssetFS::GetInstance().GetFullPath("game://kitty.glb").generic_string()); // testMesh = list_of_models[0]; // testMeshID = meshCache.addMesh(gfxDevice, testMesh); // spdlog::info("TestMesh uploaded with id: {}", testMeshID); // // auto testimgID = gfxDevice.loadImageFromFile(AssetFS::GetInstance().GetFullPath("game://kitty.png")); // spdlog::info("Test image loaded with id: {}", testimgID); // testMaterialID = materialCache.addMaterial(gfxDevice, { // .baseColor = glm::vec3(1.f), // .diffuseTexture = testimgID, // }); // spdlog::info("Test material created with id: {}", testMaterialID); // // camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f))); // auto& scene = SceneManager::GetInstance().CreateScene("Main"); // // // auto testCube = std::make_shared("TestCube"); // // auto meshComp = testCube->AddComponent(); // // meshComp->SetMeshID(testMeshID); // // meshComp->SetMaterialID(testMaterialID); // const int count = 100; // const float radius = 5.0f; // // const float orbitRadius = 5.0f; // // for (int i = 0; i < count; ++i) { // // auto childCube = std::make_shared(fmt::format("ChildCube{}", i)); // // // // auto childMeshComp = childCube->AddComponent(); // // childMeshComp->SetMeshID(testMeshID); // // childMeshComp->SetMaterialID(testMaterialID); // // // // childCube->GetTransform().SetWorldScale(glm::vec3(0.1f)); // // // // // Add orbit + self spin // // auto orbit = childCube->AddComponent(orbitRadius, glm::vec3(0.0f)); // // orbit->Randomize(1337u + (uint32_t)i); // stable random per index // // // // scene.Add(childCube); // } // // testCube->AddComponent(glm::vec3(0, 1, 0), glm::radians(10.0f)); // spin around Y, rad/sec // //rotate 180 around X axis // // testCube->GetTransform().SetLocalRotation(glm::quat(glm::vec3(glm::radians(180.0f), 0.0f, 0.0f))); // // // auto globeRoot = std::make_shared("GlobeRoot"); // globeRoot->GetTransform().SetWorldPosition(glm::vec3(0.0f)); // globeRoot->AddComponent(glm::vec3(0, 1, 0), 1.0f); // spin around Y, rad/sec // scene.Add(globeRoot); // // // // // scene.Add(testCube); // // // const auto skyboxID = AssetFS::GetInstance().GetFullPath("engine://textures/skybox.jpg"); // // const auto skyboxID = AssetFS::GetInstance().GetFullPath("engine://textures/mars.jpg"); // const auto skyboxID = AssetFS::GetInstance().GetCookedPathForFile("game://starmap_2020_4k.exr"); // // // // const auto skyboxID = AssetFS::GetInstance().GetFullPath("engine://textures/test-skybox.png"); // // // const auto vertShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.vert"); // const auto fragShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag"); // // // skyboxCubemap = std::make_unique(); // skyboxCubemap->LoadCubeMap(skyboxID.generic_string()); // skyboxCubemap->InitCubemapPipeline(vertShaderPath.generic_string(), fragShaderPath.generic_string()); // skyboxCubemap->CreateCubeMap(); // // renderer.setSkyboxTexture(skyboxCubemap->GetCubeMapImageID()); // // // // const auto planeObj = std::make_shared("GroundPlane"); // const auto planeMeshComp = planeObj->AddComponent(); // const auto planeModel = ModelLoader::LoadGLTF_CPUMeshes_MergedPerMesh(AssetFS::GetInstance().GetFullPath("game://plane.glb").generic_string()); // const auto planeMeshID = meshCache.addMesh(gfxDevice, planeModel[0]); // // const auto planeTextureID = gfxDevice.loadImageFromFile(AssetFS::GetInstance().GetFullPath("game://grass.png")); // const auto planeMaterialID = materialCache.addMaterial(gfxDevice, { // .baseColor = glm::vec3(1.f), // .textureFilteringMode = TextureFilteringMode::Nearest, // .diffuseTexture = planeTextureID, // .name = "GroundPlaneMaterial", // }); // planeMeshComp->SetMeshID(planeMeshID); // planeMeshComp->SetMaterialID(planeMaterialID); // planeObj->GetTransform().SetWorldPosition(glm::vec3(0.f, -1.0f, 0.f)); // planeObj->GetTransform().SetWorldScale(glm::vec3(10.f, 1.f, 10.f)); // scene.Add(planeObj); // // // // At the bottom of customInit(), replace the incomplete CharObj block: // // const auto CharObj = std::make_shared("Character"); // // auto charModel = ModelLoader::LoadSkinnedModel( // AssetFS::GetInstance().GetFullPath("engine://char2.fbx").generic_string() // ); // // const auto charMeshID = meshCache.addMesh(gfxDevice, charModel.meshes[0]); // // const auto charTextureID = gfxDevice.loadImageFromFile(AssetFS::GetInstance().GetFullPath("engine://char.jpg")); // const auto charMaterialID = materialCache.addMaterial(gfxDevice, { // .baseColor = glm::vec3(1.f), // .diffuseTexture = charTextureID, // .name = "CharacterMaterial", // }); // // const auto charMeshComp = CharObj->AddComponent(); // charMeshComp->SetMeshID(charMeshID); // charMeshComp->SetMaterialID(charMaterialID); // // // const auto animator = CharObj->AddComponent(); // animator->setSkeleton(std::move(charModel.skeleton)); // for (auto& clip : charModel.animations) { // animator->addClip(std::make_shared(std::move(clip))); // } // // for (const auto& clip : charModel.animations) // spdlog::info("Loaded animation: '{}' ({:.2f}s)", clip.name, clip.duration); // // if (!charModel.animations.empty()) // // animator->play("Armature|Armature|mixamo.com"); // // // animator->play(charModel.animations[0].name); // animator->play("Armature|Armature|Armature|main"); // // or: animator->play("Run", 0.2f); // 0.2s cross-fade // // CharObj->GetTransform().SetWorldPosition(glm::vec3(0.f, 0.f, 0.f)); // // CharObj->GetTransform().SetWorldScale(0.01f, 0.01f, 0.01f); // scene.Add(CharObj); } void LightKeeper::customUpdate(float dt) { camera.Update(dt); SceneManager::GetInstance().Update(); } void LightKeeper::customDraw() { renderer.beginDrawing(gfxDevice); const RenderContext ctx{ .renderer = renderer, .camera = camera, .sceneData = { .camera = camera, .ambientColor = glm::vec3(0.1f), .ambientIntensity = 0.5f, .fogColor = glm::vec3(0.5f), .fogDensity = 0.01f } }; SceneManager::GetInstance().Render(ctx); renderer.endDrawing(); const auto cmd = gfxDevice.beginFrame(); const auto& drawImage = renderer.getDrawImage(gfxDevice); renderer.draw( cmd, gfxDevice, camera, GameRenderer::SceneData{ camera, glm::vec3(0.1f), 0.5f, glm::vec3(0.5f), 0.01f }); gfxDevice.endFrame( cmd, drawImage, { .clearColor = {{0.f, 0.f, 0.5f, 1.f}}, .drawImageBlitRect = glm::ivec4{} }); } void LightKeeper::customCleanup() { auto device = gfxDevice.getDevice().device; vkDeviceWaitIdle(device); SceneManager::GetInstance().Destroy(); if (skyboxCubemap) { skyboxCubemap.reset(); } renderer.cleanup(gfxDevice); materialCache.cleanup(gfxDevice); meshCache.cleanup(gfxDevice); } void LightKeeper::onWindowResize(int newWidth, int newHeight) { renderer.resize(gfxDevice, glm::ivec2{newWidth, newHeight}); const float aspectRatio = static_cast(newWidth) / static_cast(newHeight); camera.setAspectRatio(aspectRatio); }