Compare commits

..

3 Commits

Author SHA1 Message Date
Asuro
60f1e72144 meshes! 2025-02-25 04:03:48 +01:00
Asuro
d3dcec1458 more stuff 2025-02-24 05:29:24 +01:00
Asuro
369b994755 handles 2025-02-23 02:07:26 +01:00
20 changed files with 379 additions and 49 deletions

1
src/.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.glb filter=lfs diff=lfs merge=lfs -text

View File

@@ -46,5 +46,7 @@ namespace Game
Time Time; Time Time;
PlayerData Player; PlayerData Player;
Level GameLevel; Level GameLevel;
uint64_t ImguiIniSize = 0;
char ImguiIni[4096]{0};
}; };
} // namespace Game } // namespace Game

View File

@@ -3,9 +3,12 @@
#include "Instance.h" #include "Instance.h"
#include "Level.h" #include "Level.h"
#include "Log.h" #include "Log.h"
#include "Mesh.h"
#include "Puzzle.h"
#include "SDL3/SDL_mouse.h" #include "SDL3/SDL_mouse.h"
#include "bgfx/bgfx.h" #include "bgfx/bgfx.h"
#include "imgui.h" #include "imgui.h"
#include "rendering/Rendering.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <bx/math.h> #include <bx/math.h>
#include <cstdint> #include <cstdint>
@@ -15,7 +18,9 @@ namespace Game
void EntityRenderData::Render(const Model* models, const Material* materials) void EntityRenderData::Render(const Model* models, const Material* materials)
{ {
if (ModelHandle == UINT16_MAX || MaterialHandle == UINT16_MAX) return; if (ModelHandle == UINT16_MAX || MaterialHandle == UINT16_MAX) return;
if (!Visible) return;
// Log("%u", ModelHandle);
Transform.UpdateMatrix(); Transform.UpdateMatrix();
bgfx::setTransform(Transform.M.M); bgfx::setTransform(Transform.M.M);
@@ -42,6 +47,7 @@ namespace Game
SDL_SetWindowRelativeMouseMode(GetShared().Window.SDLWindow, IsGaming); SDL_SetWindowRelativeMouseMode(GetShared().Window.SDLWindow, IsGaming);
auto& IO = ImGui::GetIO(); auto& IO = ImGui::GetIO();
IO.ConfigFlags = FlagBool(IO.ConfigFlags, ImGuiConfigFlags_NoMouse | ImGuiConfigFlags_NoKeyboard, IsGaming); IO.ConfigFlags = FlagBool(IO.ConfigFlags, ImGuiConfigFlags_NoMouse | ImGuiConfigFlags_NoKeyboard, IsGaming);
GameRendering::Get().UIVisible = IsGaming ? UIVisibilityState::Game : UIVisibilityState::Debug;
} }
} // namespace } // namespace
@@ -52,26 +58,37 @@ namespace Game
bool needReset = false; bool needReset = false;
needReset |= Cubes.Setup(storagePtr, needReset); needReset |= Cubes.Setup(storagePtr, needReset);
needReset |= Tests.Setup(storagePtr, needReset); needReset |= Tests.Setup(storagePtr, needReset);
needReset |= PuzzleTiles.Setup(storagePtr, needReset);
PuzzleData.Setup();
if (Cubes.Count == 0) if (Cubes.Count == 0)
{ {
for (uint32_t yy = 0; yy < 11; ++yy) for (uint32_t yy = 0; yy < 11; ++yy)
{ {
for (uint32_t xx = 0; xx < 11; ++xx) for (uint32_t xx = 0; xx < 11; ++xx)
{ {
Cube* c = Cubes.New(); Cube* c = Cubes.Get(Cubes.New());
if (c) if (c)
{ {
c->TestX = xx; c->TestX = xx;
c->TestY = yy; c->TestY = yy;
c->Setup();
} }
} }
} }
Cubes.New(); // Floor
Cube* floor = Cubes.New();
} }
if (Tests.Count == 0) if (Tests.Count == 0)
{ {
Tests.New(); Tests.Get(Tests.New())->Setup();
}
if (PuzzleTiles.Count == 0)
{
for (uint32_t puzI = 0; puzI < BX_COUNTOF(Puzzles); ++puzI)
{
Puzzles[puzI].Setup();
}
} }
UpdatePlayerInputMode(); UpdatePlayerInputMode();
@@ -82,6 +99,7 @@ namespace Game
START_PERF(); START_PERF();
PlayerData& player = GetInstance().Player; PlayerData& player = GetInstance().Player;
// Input
float delta = GetInstance().Time.Delta; float delta = GetInstance().Time.Delta;
delta = 1.0f / 144.0f; delta = 1.0f / 144.0f;
constexpr float moveSpeed = 10.0f; constexpr float moveSpeed = 10.0f;
@@ -138,8 +156,18 @@ namespace Game
player.PlayerCamTransform.RotateLocal({player.WalkXRot, 0.0f, 0.0f}); player.PlayerCamTransform.RotateLocal({player.WalkXRot, 0.0f, 0.0f});
} }
Cubes.Update(); // Cubes
Tests.Update(); for (uint16_t i = 0; i < Cubes.Count; ++i)
{
Cubes.Get({i})->Update();
}
// Puzzle tiles
for (int32_t i = 0; i < BX_COUNTOF(Puzzles); ++i)
{
Puzzles[i].Update();
}
END_PERF(GetShared().Window.PerfCounters, PerfCounterType::GameLevelUpdate, GetShared().Window.FrameCounter); END_PERF(GetShared().Window.PerfCounters, PerfCounterType::GameLevelUpdate, GetShared().Window.FrameCounter);
} }
@@ -160,21 +188,24 @@ namespace Game
{ {
player.FreeflyCamTransform.UpdateMatrix(); player.FreeflyCamTransform.UpdateMatrix();
bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj); bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj);
bgfx::dbgTextPrintf(1, 0, 0b1100, "NOCLIP");
} }
else else
{ {
player.PlayerCamTransform.UpdateMatrix(); player.PlayerCamTransform.UpdateMatrix();
bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj); bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj);
bgfx::dbgTextPrintf(1, 0, 0b1100, " ");
} }
Cubes.Render(models, materials); // Cubes.Render(models, materials);
Tests.Render(models, materials); Tests.Render(models, materials);
PuzzleTiles.Render(models, materials);
} }
void Cube::Setup() void Cube::Setup()
{ {
EData.MaterialHandle = 0; EData.MaterialHandle = 0;
EData.ModelHandle = 0; EData.ModelHandle = GameRendering::Get().GetModelHandleFromPath("models/cube.gltf");
} }
void Cube::Update() void Cube::Update()
@@ -200,13 +231,45 @@ namespace Game
void TestEntity::Setup() void TestEntity::Setup()
{ {
EData.MaterialHandle = 0; EData.MaterialHandle = 0;
EData.ModelHandle = 1; EData.ModelHandle = GameRendering::Get().GetModelHandleFromPath("models/zurg.gltf");
EData.Transform.Position = {0.0f, 0.0f, 10.0f}; EData.Transform.Position = {0.0f, 0.0f, 10.0f};
}
void TestEntity::Update()
{
EData.TestColor[0] = 0.0f; EData.TestColor[0] = 0.0f;
} }
void WorldPuzzle::Setup()
{
Data.PlacedCardCount = 16;
for (int32_t i = 0; i < 16; ++i)
{
Data.PlacedCards[i].RefCard = {0};
Data.PlacedCards[i].Position = {int8_t(i % 4), int8_t(i / 4)};
}
for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI)
{
const Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI];
auto& tiles = GetInstance().GameLevel.PuzzleTiles;
TileHandles[cardI] = tiles.New();
bx::Vec3 Pos = {
WorldPosition.x + card.Position.X * WorldCardSize.x,
WorldPosition.y,
WorldPosition.z + card.Position.Y * WorldCardSize.y,
};
auto& tile = *tiles.Get(TileHandles[cardI]);
tile.EData.Transform.Position = Pos;
tile.EData.MaterialHandle = 0;
}
}
void WorldPuzzle::Update()
{
for (int32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI)
{
Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI];
if (!card.RefCard.IsValid()) continue;
const Puzzle::StaticPuzzleCard& cData = Puzzle::StaticPuzzleData::Get().GetCard(card.RefCard);
GetInstance().GameLevel.PuzzleTiles.Get(TileHandles[cardI])->EData.ModelHandle = cData.ModelHandle;
}
}
} // namespace Game } // namespace Game

View File

@@ -2,10 +2,17 @@
#include "../engine/Shared.h" #include "../engine/Shared.h"
#include "Global.h" #include "Global.h"
#include "Log.h" #include "Log.h"
#include "Puzzle.h"
#include "rendering/Rendering.h" #include "rendering/Rendering.h"
#include <bgfx/bgfx.h> #include <bgfx/bgfx.h>
#include <cstdint> #include <cstdint>
#define ENTITY_HANDLE(X) \
struct X \
{ \
uint16_t Idx = UINT16_MAX; \
};
namespace Game namespace Game
{ {
struct EntityRenderData struct EntityRenderData
@@ -14,10 +21,12 @@ namespace Game
Transform Transform; Transform Transform;
uint16_t MaterialHandle = UINT16_MAX; uint16_t MaterialHandle = UINT16_MAX;
uint16_t ModelHandle = UINT16_MAX; uint16_t ModelHandle = UINT16_MAX;
bool Visible = true;
void Render(const Model* models, const Material* materials); void Render(const Model* models, const Material* materials);
}; };
ENTITY_HANDLE(CubeHandle);
struct Cube struct Cube
{ {
int32_t TestX = -1; int32_t TestX = -1;
@@ -28,15 +37,21 @@ namespace Game
void Update(); void Update();
}; };
ENTITY_HANDLE(TestEntityHandle);
struct TestEntity struct TestEntity
{ {
EntityRenderData EData; EntityRenderData EData;
void Setup(); void Setup();
void Update();
}; };
template <typename T, uint32_t C> class EntityManager ENTITY_HANDLE(PuzzleTileEntityHandle);
struct PuzzleTileEntity
{
EntityRenderData EData;
};
template <typename T, typename HandleT, uint32_t C> class EntityManager
{ {
public: public:
uint16_t Count = 0; uint16_t Count = 0;
@@ -59,58 +74,66 @@ namespace Game
return changed; return changed;
} }
T* New() HandleT New()
{ {
if (Data == nullptr) if (Data == nullptr)
{ {
Log("Accessed EntityManager before setup!"); Log("Accessed EntityManager before setup!");
return nullptr; return {};
} }
if (Count >= C) if (Count >= C)
{ {
Log("Too many entities!"); Log("Too many entities!");
return nullptr; return {};
} }
Data[Count] = {}; Data[Count] = {};
Data[Count].Setup(); HandleT H;
T* result = &Data[Count]; H.Idx = Count;
++Count; ++Count;
return result; return H;
} }
T* Get(uint16_t idx) T* Get(HandleT handle)
{ {
if (idx > Count) if (handle.Idx > Count)
{ {
Log("OOB Access!"); Log("OOB Access!");
return nullptr; return nullptr;
} }
return &Data[idx]; return &Data[handle.Idx];
}
void Update()
{
for (uint32_t i = 0; i < Count; ++i)
{
Data[i].Update();
}
} }
void Render(const Model* models, const Material* materials) void Render(const Model* models, const Material* materials)
{ {
for (int32_t i = 0; i < Count; ++i) for (uint16_t i = 0; i < Count; ++i)
{ {
T* c = Get(i); T* c = Get({i});
if (c) c->EData.Render(models, materials); if (c) c->EData.Render(models, materials);
} }
} }
}; };
struct WorldPuzzle
{
static constexpr Vec2 WorldCardSize{10.0f, 10.0f};
Puzzle::PuzzleData Data;
Vec3 WorldPosition;
PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle];
void Setup();
void Update();
};
class Level class Level
{ {
public: public:
EntityManager<Cube, 1024> Cubes; EntityManager<Cube, CubeHandle, 1024> Cubes;
EntityManager<TestEntity, 32> Tests; EntityManager<TestEntity, TestEntityHandle, 32> Tests;
EntityManager<PuzzleTileEntity, PuzzleTileEntityHandle, 1024> PuzzleTiles;
public:
Puzzle::StaticPuzzleData PuzzleData;
WorldPuzzle Puzzles[1];
public: public:
void Setup(GameData& data); void Setup(GameData& data);

View File

@@ -1,6 +1,12 @@
#include "Log.h" #include "Log.h"
#include "Mesh.h" #include "Mesh.h"
#include "bx/bx.h" #include "bx/bx.h"
#include "bx/error.h"
#include "bx/file.h"
#include "bx/filepath.h"
#include "bx/hash.h"
#include "bx/string.h"
#include "rendering/Rendering.h"
#define TINYGLTF_IMPLEMENTATION #define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@@ -9,7 +15,7 @@
namespace Game namespace Game
{ {
void LoadMesh(Model& mesh, const char* path) bool LoadMesh(Model& mesh, const char* path, bool isBinary)
{ {
mesh.VertLayout.begin() mesh.VertLayout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
@@ -22,14 +28,23 @@ namespace Game
tinygltf::TinyGLTF loader; tinygltf::TinyGLTF loader;
std::string warn; std::string warn;
std::string err; std::string err;
bool loadSuccess = loader.LoadASCIIFromFile(&model, &err, &warn, path);
bool loadSuccess;
if (isBinary)
{
loadSuccess = loader.LoadBinaryFromFile(&model, &err, &warn, path);
}
else
{
loadSuccess = loader.LoadASCIIFromFile(&model, &err, &warn, path);
}
if (!warn.empty()) Log("WARN: %s", warn.c_str()); if (!warn.empty()) Log("WARN: %s", warn.c_str());
if (!err.empty()) Log("ERR: %s", err.c_str()); if (!err.empty()) Log("ERR: %s", err.c_str());
if (!loadSuccess) if (!loadSuccess)
{ {
Log("Model load failed!"); Log("Model load failed!");
return; return false;
} }
tinygltf::Primitive primitive = model.meshes[0].primitives[0]; tinygltf::Primitive primitive = model.meshes[0].primitives[0];
@@ -69,5 +84,71 @@ namespace Game
} }
mesh.VertexBuffer = bgfx::createVertexBuffer(vbMem, mesh.VertLayout); mesh.VertexBuffer = bgfx::createVertexBuffer(vbMem, mesh.VertLayout);
} }
return true;
}
void LoadModels(Model* models, uint32_t& outCount)
{
bx::Error err;
bx::DirectoryReader reader{};
if (!reader.open("models", &err) || !err.isOk())
{
Log("Failed to read models dir: %s", err.getMessage());
}
bx::FileInfo info;
int32_t modelFilePathCount = 0;
bx::FilePath modelFilePaths[GameRendering::MaxModels];
bool modelFileIsBinary[GameRendering::MaxModels]{false};
while (err.isOk())
{
int32_t res = reader.read(&info, sizeof(info), &err);
if (res == 0) break; // EOF
if (res != sizeof(info))
{
Log("Dir iter error: %s", err.getMessage());
break;
}
const bx::StringView ext = info.filePath.getExt();
bool isBinary = bx::strCmp(ext, ".glb") == 0;
bool isText = bx::strCmp(ext, ".gltf") == 0;
if ((isBinary || isText) && !ext.isEmpty() && info.type == bx::FileType::File)
{
if (modelFilePathCount >= GameRendering::MaxModels)
{
Log("Model limit reached!");
break;
}
modelFilePaths[modelFilePathCount] = info.filePath;
modelFileIsBinary[modelFilePathCount] = isBinary;
modelFilePathCount++;
}
}
Log("Found %u models!", modelFilePathCount);
int32_t writeI = 0;
for (int32_t i = 0; i < modelFilePathCount; ++i)
{
bx::FilePath fullPath = bx::FilePath{"models"};
fullPath.join(modelFilePaths[i].getCPtr());
Model& mod = models[writeI];
if (LoadMesh(mod, fullPath.getCPtr(), modelFileIsBinary[i]))
{
mod.AssetHandle = CrcPath(fullPath.getCPtr());
++writeI;
}
else
{
Log("Failed to load model: %s", fullPath.getCPtr());
}
}
outCount = writeI;
}
uint32_t CrcPath(const char* path)
{
bx::HashCrc32 hash;
hash.begin();
hash.add(path);
return hash.end();
} }
} // namespace Game } // namespace Game

View File

@@ -4,5 +4,7 @@
namespace Game namespace Game
{ {
void LoadMesh(Model& mesh, const char* path); bool LoadMesh(Model& mesh, const char* path, bool isBinary);
} void LoadModels(Model* models, uint32_t& outCount);
uint32_t CrcPath(const char* path);
} // namespace Game

View File

@@ -1,4 +1,8 @@
#include "Log.h"
#include "Puzzle.h" #include "Puzzle.h"
#include "rendering/Rendering.h"
#include "bx/bx.h"
#include <cassert> #include <cassert>
namespace namespace
@@ -9,10 +13,33 @@ namespace
{0, 1}, {0, 1},
{1, 0}, {1, 0},
}; };
}
Puzzle::StaticPuzzleData* StaticDataInstance = nullptr;
} // namespace
namespace Puzzle namespace Puzzle
{ {
void StaticPuzzleData::Setup()
{
StaticDataInstance = this;
Log("Setting up static puzzle data");
for (int32_t i = 0; i < BX_COUNTOF(Cards); ++i)
{
Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb");
}
}
StaticPuzzleData& StaticPuzzleData::Get()
{
assert(StaticDataInstance != nullptr);
return *StaticDataInstance;
}
const StaticPuzzleCard& StaticPuzzleData::GetCard(StaticPuzzleCardHandle H) const
{
assert(H.IsValid());
return Cards[H.Idx];
}
bool PuzzleNode::HasElement(PuzzleElementType search) const bool PuzzleNode::HasElement(PuzzleElementType search) const
{ {
for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i)
@@ -37,11 +64,29 @@ namespace Puzzle
return MaxAvailableCount - UsedCount; return MaxAvailableCount - UsedCount;
} }
const PuzzleNode& PuzzleData::GetNodeAt(PuzPos pos) const
{
assert(pos.X < Config::MaxPuzzleSizeCards && pos.Y < Config::MaxPuzzleSizeCards && pos.X >= 0 && pos.Y >= 0);
return PlacedNodes[pos.Y * Config::MaxPuzzleSizeCards + pos.X];
}
PuzzleElementType PuzzleData::GetElementAt(ElemPos pos) const
{
assert(pos.ElemIdx < Config::MaxElementsPerTile);
const PuzzleNode& node = GetNodeAt(pos.Position);
return node.PlacedTypes[pos.ElemIdx];
}
bool PuzzleSolver::IsPuzzleSolved(const PuzzleData& puzzle) bool PuzzleSolver::IsPuzzleSolved(const PuzzleData& puzzle)
{ {
bool IsSolved = true; bool IsSolved = true;
for (uint32_t i = 0; i < puzzle.GoalPositionCount; ++i) for (uint32_t i = 0; i < puzzle.GoalPositionCount; ++i)
{ {
if (!IsExitSatisfied(puzzle, puzzle.GoalPositions[i]))
{
IsSolved = false;
break;
}
} }
return IsSolved; return IsSolved;
} }

View File

@@ -64,11 +64,25 @@ namespace Puzzle
struct StaticPuzzleCard struct StaticPuzzleCard
{ {
PuzzleNode Nodes[Config::NodesPerCard]; PuzzleNode Nodes[Config::NodesPerCard];
uint16_t ModelHandle = 0;
}; };
struct StaticPuzzleCardHandle struct StaticPuzzleCardHandle
{ {
uint16_t Idx = UINT16_MAX; uint16_t Idx = UINT16_MAX;
bool IsValid()
{
return Idx != UINT16_MAX;
}
};
struct StaticPuzzleData
{
StaticPuzzleCard Cards[64];
void Setup();
static StaticPuzzleData& Get();
const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) const;
}; };
struct PlacedPuzzleCard struct PlacedPuzzleCard

View File

@@ -8,8 +8,8 @@
#include "SDL3/SDL_events.h" #include "SDL3/SDL_events.h"
#include "backends/imgui_impl_sdl3.h" #include "backends/imgui_impl_sdl3.h"
#include "bgfx/defines.h" #include "bgfx/defines.h"
#include "bx/bx.h"
#include "bx/filepath.h" #include "bx/filepath.h"
#include "bx/math.h"
#include "bx/timer.h" #include "bx/timer.h"
#include <bgfx/bgfx.h> #include <bgfx/bgfx.h>
#include <bimg/bimg.h> #include <bimg/bimg.h>
@@ -190,11 +190,21 @@ namespace Game
return handle; return handle;
} }
GameRendering* Instance = nullptr;
} // namespace } // namespace
GameRendering& GameRendering::Get()
{
assert(Instance != nullptr);
return *Instance;
}
void GameRendering::Setup() void GameRendering::Setup()
{ {
Log("--- RENDERING STARTUP ---"); Log("--- RENDERING STARTUP ---");
if (Instance != nullptr) Log("Warning, old rendering wasn't destroyed!");
Instance = this;
SharedData& shared = GetShared(); SharedData& shared = GetShared();
bgfx::Init init; bgfx::Init init;
@@ -228,8 +238,7 @@ namespace Game
Textures[0].Handle = Textures[0].Handle =
loadTexture(bx::FilePath{"models/body.dds"}, BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE, 0, nullptr, nullptr); loadTexture(bx::FilePath{"models/body.dds"}, BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE, 0, nullptr, nullptr);
Textures[0].SamplerHandle = DefaultSampler; Textures[0].SamplerHandle = DefaultSampler;
LoadMesh(Models[0], "models/cube.gltf"); LoadModels(Models, ModelCount);
LoadMesh(Models[1], "models/zurg.gltf");
Materials[0] = Materials[0] =
Material::LoadFromShader("vert", "frag", MainViewID, Textures[0].Handle, Textures[0].SamplerHandle); Material::LoadFromShader("vert", "frag", MainViewID, Textures[0].Handle, Textures[0].SamplerHandle);
@@ -250,9 +259,15 @@ namespace Game
// platIO.Platform_SetWindowSize = TODO; // platIO.Platform_SetWindowSize = TODO;
// platIO.Platform_RenderWindow = TODO; // platIO.Platform_RenderWindow = TODO;
if (!GetInstance().IsInitialized) GameInstance& inst = GetInstance();
if (!inst.IsInitialized)
{ {
GetInstance().Time.StartTime = bx::getHPCounter(); inst.Time.StartTime = bx::getHPCounter();
}
if (inst.ImguiIniSize > 0)
{
ImGui::LoadIniSettingsFromMemory(inst.ImguiIni, inst.ImguiIniSize);
} }
} }
@@ -305,7 +320,24 @@ namespace Game
imguiBeginFrame(20); imguiBeginFrame(20);
ImGui_ImplSDL3_NewFrame(); ImGui_ImplSDL3_NewFrame();
ImGui::DockSpaceOverViewport(0, 0, ImGuiDockNodeFlags_PassthruCentralNode); ImGui::DockSpaceOverViewport(0, 0, ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::ShowDemoWindow();
if (UIVisible == UIVisibilityState::Debug)
{
if (ImGui::Begin("Rendering"))
{
if (ImGui::Button("Reload Meshes"))
{
LoadModels(Models, ModelCount);
}
if (ImGui::Button("Reload Level"))
{
auto& lvl = GetInstance().GameLevel;
lvl = {};
lvl.Setup(shared.Game);
}
}
ImGui::End();
}
GetInstance().GameLevel.Update(); GetInstance().GameLevel.Update();
GetInstance().GameLevel.Render(MainViewID, Models, Materials); GetInstance().GameLevel.Render(MainViewID, Models, Materials);
@@ -333,9 +365,15 @@ namespace Game
void GameRendering::Shutdown() void GameRendering::Shutdown()
{ {
Log("--- RENDERING_SHUTDOWN ---");
const char* iniData = ImGui::SaveIniSettingsToMemory(reinterpret_cast<uint64_t*>(&GetInstance().ImguiIniSize));
assert(GetInstance().ImguiIniSize <= BX_COUNTOF(GameInstance::ImguiIni));
bx::memCopy(
GetInstance().ImguiIni, iniData, bx::min(GetInstance().ImguiIniSize, BX_COUNTOF(GameInstance::ImguiIni)));
ImGui_ImplSDL3_Shutdown(); ImGui_ImplSDL3_Shutdown();
imguiDestroy(); imguiDestroy();
bgfx::shutdown(); bgfx::shutdown();
Instance = nullptr;
} }
Material Material::LoadFromShader( Material Material::LoadFromShader(
@@ -356,4 +394,18 @@ namespace Game
mat.ViewID = view; mat.ViewID = view;
return mat; return mat;
} }
uint16_t GameRendering::GetModelHandleFromPath(const char* path)
{
uint32_t AssetHandle = CrcPath(path);
for (int32_t i = 0; i < ModelCount; ++i)
{
if (Models[i].AssetHandle == AssetHandle)
{
return i;
}
}
return 0;
}
} // namespace Game } // namespace Game

View File

@@ -32,6 +32,7 @@ namespace Game
bgfx::VertexBufferHandle VertexBuffer; bgfx::VertexBufferHandle VertexBuffer;
bgfx::IndexBufferHandle IndexBuffer; bgfx::IndexBufferHandle IndexBuffer;
bgfx::VertexLayout VertLayout; bgfx::VertexLayout VertLayout;
uint32_t AssetHandle = UINT16_MAX;
}; };
struct Material struct Material
@@ -54,13 +55,28 @@ namespace Game
bgfx::UniformHandle sampler = BGFX_INVALID_HANDLE); bgfx::UniformHandle sampler = BGFX_INVALID_HANDLE);
}; };
enum class UIVisibilityState
{
None,
Game,
Debug,
};
class GameRendering class GameRendering
{ {
public:
static constexpr uint32_t MaxModels = 64;
static GameRendering& Get();
public:
UIVisibilityState UIVisible = UIVisibilityState::Game;
private: private:
bgfx::UniformHandle DefaultSampler; bgfx::UniformHandle DefaultSampler;
Texture Textures[8]; Texture Textures[8];
Material Materials[8]; Material Materials[8];
Model Models[8]; uint32_t ModelCount = 0;
Model Models[MaxModels];
int32_t LastWidth = 0; int32_t LastWidth = 0;
int32_t LastHeight = 0; int32_t LastHeight = 0;
uint32_t ResetFlags = BGFX_RESET_VSYNC; uint32_t ResetFlags = BGFX_RESET_VSYNC;
@@ -70,5 +86,6 @@ namespace Game
void Setup(); void Setup();
void Update(); void Update();
void Shutdown(); void Shutdown();
uint16_t GetModelHandleFromPath(const char* path);
}; };
} // namespace Game } // namespace Game

BIN
src/models/ConcretePlane.glb LFS Normal file

Binary file not shown.

BIN
src/models/blocked.glb LFS Normal file

Binary file not shown.

BIN
src/models/e!.glb LFS Normal file

Binary file not shown.

BIN
src/models/e+.glb LFS Normal file

Binary file not shown.

BIN
src/models/w corner long.glb LFS Normal file

Binary file not shown.

BIN
src/models/w corner short.glb LFS Normal file

Binary file not shown.

BIN
src/models/w straight.glb LFS Normal file

Binary file not shown.

BIN
src/models/w! corner short.glb LFS Normal file

Binary file not shown.

BIN
src/models/w! straight.glb LFS Normal file

Binary file not shown.

BIN
src/models/w+ straight.glb LFS Normal file

Binary file not shown.