diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b2810b..1b828e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_policy(SET CMP0141 NEW) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,EditAndContinue,ProgramDatabase>" CACHE STRING "MSVC debug information format") project( NavKit - VERSION 2.13.0 + VERSION 2.14.0 DESCRIPTION "An app to create NAVP and AIRG files for use with Hitman: World of Assassination" LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) diff --git a/include/NavKit/NavKitConfig.h b/include/NavKit/NavKitConfig.h index 08bb7ad..d566326 100644 --- a/include/NavKit/NavKitConfig.h +++ b/include/NavKit/NavKitConfig.h @@ -1,3 +1,3 @@ #define NavKit_VERSION_MAJOR "2" -#define NavKit_VERSION_MINOR "13" +#define NavKit_VERSION_MINOR "14" #define NavKit_VERSION_PATCH "0" diff --git a/include/NavKit/module/InputHandler.h b/include/NavKit/module/InputHandler.h index 25b36ec..15ae881 100644 --- a/include/NavKit/module/InputHandler.h +++ b/include/NavKit/module/InputHandler.h @@ -34,6 +34,7 @@ class InputHandler { float moveUp; float moveDown; + static constexpr int MENU_HEIGHT = 20; static constexpr int QUIT = 1; static constexpr float BASE_KEYBOARD_SPEED = 22.0f; static constexpr float SHIFT_SPEED_MULTIPLIER = 4.0f; diff --git a/include/NavKit/module/Navp.h b/include/NavKit/module/Navp.h index 9450cf2..3a00c3c 100644 --- a/include/NavKit/module/Navp.h +++ b/include/NavKit/module/Navp.h @@ -55,6 +55,9 @@ class Navp { static void updateNavMeshBuffers(const NavPower::NavMesh* navMesh, int selectedIndex); + static int getTotalAreaCount(const NavPower::NavMesh* navMesh); + static NavPower::Area& getAreaByIndex(const NavPower::NavMesh* navMesh, int index); + static void updateHitTestBuffers(const NavPower::NavMesh* navMesh); void renderPfSeedPoints() const; diff --git a/include/NavWeakness/NavPower.h b/include/NavWeakness/NavPower.h index b160246..d7563e9 100644 --- a/include/NavWeakness/NavPower.h +++ b/include/NavWeakness/NavPower.h @@ -1,5 +1,5 @@ /* -NavPower.h - v1.2.0 +NavPower.h - v2.0.0 A header file for use with NavPower's binary navmesh files. Licensed under the MIT License @@ -149,11 +149,11 @@ namespace NavPower uint32_t m_kdTreeBytes; uint32_t m_linkRecordBytes = 0; uint32_t m_totalBytes; - float m_buildScale = 2.0; - float m_voxSize = 0.1; - float m_radius = 0.2; - float m_stepHeight = 0.3; - float m_height = 1.8; // Human Height + float m_buildScale = 2.0f; + float m_voxSize = 0.1f; + float m_radius = 0.2f; + float m_stepHeight = 0.3f; + float m_height = 1.8f; // Human Height BBox m_bbox; Axis m_buildUpAxis = Axis::Z; // In NAVPs from Hitman WoA the padding isn't just 0x00 @@ -408,22 +408,19 @@ namespace NavPower bool compareY(Area& a1, Area& a2); bool compareZ(Area& a1, Area& a2); - class NavMesh + class NavGraph { public: - Binary::Header* m_hdr; - Binary::SectionHeader* m_sectHdr; - Binary::NavSetHeader* m_setHdr; - Binary::NavGraphHeader* m_graphHdr; + Binary::NavGraphHeader* m_hdr; std::vector m_areas; Binary::KDTreeData* m_kdTreeData; Binary::KDNode* m_rootKDNode; - NavMesh() {}; - NavMesh(const char* p_NavMeshPath) { readJson(p_NavMeshPath);}; + NavGraph() {}; + NavGraph(auto s_NavGraphJson); - NavMesh(uintptr_t p_data, uint32_t p_filesize) { read(p_data, p_filesize); }; + NavGraph(uintptr_t p_data) { read(p_data); }; // Build m_areas pointer to index map so the pointers can be replaced with indices (+1) in the JSON file std::map AreaPointerToIndexMap(); @@ -451,10 +448,10 @@ namespace NavPower uint32_t generateKdTree(uintptr_t s_nodePtr, std::vector& s_areas, std::map& p_AreaPointerToNavGraphOffsetMap); void writeJson(std::ostream& f); - void readJson(const char* p_NavMeshPath); + void readJson(auto s_NavGraphJson); void writeBinary(std::ostream& f); - void read(uintptr_t p_data, uint32_t p_filesize); + void read(uintptr_t& p_data); // This parses the k-d tree and outputs it as a vector of bounding boxes std::map>> ParseKDTree() @@ -507,6 +504,44 @@ namespace NavPower } }; + class Section + { + public: + Binary::SectionHeader* m_hdr; + Binary::NavSetHeader* m_setHdr; + std::vector m_aNavGraphs; + + Section(){}; + Section(uintptr_t& p_data) { read(p_data); }; + + void read(uintptr_t& p_data); + + void readJson(auto p_SectionJson); + + void writeJson(std::ofstream& f); + + void writeBinary(std::ostream& f); + }; + + class NavMesh + { + public: + Binary::Header* m_hdr; + std::vector
m_aSections; + + NavMesh() {}; + NavMesh(const char* p_NavGraphJsonPath); + NavMesh(uintptr_t p_data, uint32_t p_filesize) { read(p_data, p_filesize); }; + + void read(uintptr_t p_data, uint32_t p_filesize); + + void readJson(const char* p_NavGraphJsonPath); + + void writeJson(std::ofstream& f); + + void writeBinary(std::ostream& f); + }; + // This function was made by github.com/OrfeasZ aka NoFaTe uint32_t CalculateChecksum(void* p_Data, uint32_t p_Size); } // namespace NavPower \ No newline at end of file diff --git a/lib/Debug/NavWeakness.dll b/lib/Debug/NavWeakness.dll index 3324b02..655dca2 100644 Binary files a/lib/Debug/NavWeakness.dll and b/lib/Debug/NavWeakness.dll differ diff --git a/lib/Release/NavWeakness.dll b/lib/Release/NavWeakness.dll index 95917f3..91e8e2e 100644 Binary files a/lib/Release/NavWeakness.dll and b/lib/Release/NavWeakness.dll differ diff --git a/src/NavKit.cpp b/src/NavKit.cpp index eb58689..c2cc0db 100644 --- a/src/NavKit.cpp +++ b/src/NavKit.cpp @@ -20,6 +20,7 @@ * SOFTWARE. */ #include +#include #include #include "../include/NavKit/module/Airg.h" #include "../include/NavKit/module/Gui.h" @@ -34,8 +35,48 @@ #include "../include/NavKit/util/ErrorHandler.h" #include "../include/NavKit/util/FileUtil.h" #include "../include/NavKit/util/UpdateChecker.h" +#include + #undef main +void runFrameIteration() { + Renderer::getInstance().renderFrame(); + InputHandler::getInstance().hitTest(); + Gui::getInstance().drawGui(); + + SceneExtract::getInstance().finalizeExtractScene(); + SceneMesh::getInstance().finalizeSceneMeshBuild(); + Navp::getInstance().finalizeBuild(); + SceneMesh::getInstance().finalizeLoad(); + Airg::getInstance().finalizeSave(); + SceneMesh::getInstance().finalizeExtractResources(); + Renderer::getInstance().finalizeFrame(); +} + +bool mainLoopIteration() { + if (InputHandler::getInstance().handleInput() == InputHandler::QUIT) { + return false; + } + runFrameIteration(); + return true; +} + +static int SDLCALL eventFilter(void* userdata, SDL_Event* event) { + if (event->type == SDL_SYSWMEVENT) { + const SDL_SysWMmsg* wmMsg = event->syswm.msg; + if (wmMsg->subsystem == SDL_SYSWM_WINDOWS) { + if (wmMsg->msg.win.msg == WM_ENTERMENULOOP) { + SetTimer(wmMsg->msg.win.hwnd, 1, 1, nullptr); + } else if (wmMsg->msg.win.msg == WM_EXITMENULOOP) { + KillTimer(wmMsg->msg.win.hwnd, 1); + } else if (wmMsg->msg.win.msg == WM_TIMER) { + runFrameIteration(); + } + } + } + return 1; +} + int SDL_main(const int argc, char** argv) { CPPTRACE_TRY { @@ -49,34 +90,16 @@ int SDL_main(const int argc, char** argv) { } renderer.initShaders(); SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(eventFilter, nullptr); UpdateChecker& updateChecker = UpdateChecker::getInstance(); updateChecker.startUpdateCheck(); - SceneExtract& sceneExtract = SceneExtract::getInstance(); - Navp& navp = Navp::getInstance(); - SceneMesh& obj = SceneMesh::getInstance(); - Airg& airg = Airg::getInstance(); - InputHandler& inputHandler = InputHandler::getInstance(); Menu::updateMenuState(); - Gui& gui = Gui::getInstance(); bool isRunning = true; Logger::log(NK_INFO, "NavKit initialized."); while (isRunning) { - if (inputHandler.handleInput() == InputHandler::QUIT) { - isRunning = false; - } - renderer.renderFrame(); - inputHandler.hitTest(); - gui.drawGui(); - - sceneExtract.finalizeExtractScene(); - obj.finalizeSceneMeshBuild(); - navp.finalizeBuild(); - obj.finalizeLoad(); - airg.finalizeSave(); - obj.finalizeExtractResources(); - renderer.finalizeFrame(); + isRunning = mainLoopIteration(); } NFD_Quit(); diff --git a/src/extern/RecastDemo/Sample.cpp b/src/extern/RecastDemo/Sample.cpp index d0d1c14..775290a 100644 --- a/src/extern/RecastDemo/Sample.cpp +++ b/src/extern/RecastDemo/Sample.cpp @@ -457,133 +457,132 @@ struct PolyInfo { void Sample::saveAll(const char* s_OutputFileName) { - const dtNavMesh* mesh = m_navMesh; - if (!mesh) return; - - remove(s_OutputFileName); - - std::ofstream f(s_OutputFileName); - f << std::fixed << std::boolalpha; - f << "{\"Areas\":["; - std::vector tilePolyCounts; - for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) { - const dtMeshTile* tile = mesh->getTile(tileIndex); - if (!tile || !tile->header || !tile->dataSize) { - tilePolyCounts.push_back(0); - continue; - } - tilePolyCounts.push_back(tile->header->polyCount); - } - int totalAreaCount = 0; - for (int count : tilePolyCounts) { - totalAreaCount += count; - } - std::vector allPolyflags; - int curPoly = 0; - std::vector indexToPolyInfo(totalAreaCount, {-1, -1}); - - for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) { - const dtMeshTile *tile = mesh->getTile(tileIndex); - if (!tile || !tile->header || !tile->dataSize) { - continue; - } - for (int polyIndex = 0; polyIndex < tile->header->polyCount; polyIndex++) { - allPolyflags.push_back(tile->polys[polyIndex].flags); - if (tile->polys[polyIndex].flags != SAMPLE_POLYFLAGS_DISABLED) { - const int totalIndex = getTotalIndex(tileIndex, polyIndex, tilePolyCounts); - indexToPolyInfo[totalIndex] = {tileIndex, polyIndex, curPoly++}; - } - } - } - curPoly = 0; - bool validAreaFound = false; - // Store tiles. - for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) - { - const dtMeshTile* tile = mesh->getTile(tileIndex); - if (!tile || !tile->header || !tile->dataSize) continue; - int numPolys = tile->header->polyCount; - for (int polyIndex = 0; polyIndex < numPolys; polyIndex++) { - const dtPoly& poly = tile->polys[polyIndex]; - - const int totalIndex = getTotalIndex(tileIndex, polyIndex, tilePolyCounts); - if (poly.flags == SAMPLE_POLYFLAGS_DISABLED) { - continue; - } - if (validAreaFound) { - f << ","; - } - if (!validAreaFound) { - validAreaFound = true; - } - f << "{"; - f << R"("Area":{"Index":)" << indexToPolyInfo[totalIndex].totalPolyIndex; - f << "},"; - f << "\"Edges\":["; - - int numVerts = poly.vertCount; - for (int vi = 0; vi < numVerts; vi++) { - unsigned short vertIndex = poly.verts[vi]; - float X = tile->verts[vertIndex * 3]; - float Y = -tile->verts[vertIndex * 3 + 2]; - float Z = tile->verts[vertIndex * 3 + 1]; - f << "{"; - for (unsigned int linkIndex = poly.firstLink; linkIndex != DT_NULL_LINK; linkIndex = tile->links[linkIndex].next) - { - const dtLink& link = tile->links[linkIndex]; - if (link.edge != vi) { - continue; - } - const dtMeshTile* targetTile = nullptr; - const dtPoly* targetPoly = nullptr; - mesh->getTileAndPolyByRef(link.ref, &targetTile, &targetPoly); - if (targetTile && targetPoly) - { - int targetTileIndex = -1; - for (int i = 0; i < mesh->getMaxTiles(); ++i) { - if (mesh->getTile(i) == targetTile) { - targetTileIndex = i; - break; - } - } - if (targetTileIndex != -1) { - int targetPolyIndex = -1; - for (int i = 0; i < targetTile->header->polyCount; ++i) { - if (&targetTile->polys[i] == targetPoly) { - targetPolyIndex = i; - break; - } - } - if (targetPolyIndex != -1) { - int neiTotalIndex = getTotalIndex(targetTileIndex, targetPolyIndex, tilePolyCounts); - if (neiTotalIndex < totalAreaCount && neiTotalIndex != -1) { - if (allPolyflags[neiTotalIndex] != SAMPLE_POLYFLAGS_DISABLED) { - f << "\"Adjacent Area\":"; - f << indexToPolyInfo[neiTotalIndex].totalPolyIndex + 1 << ","; - } - } - } - } - } - } - f << "\"Position\":"; - f << "{"; - f << "\"X\":" << X << ","; - f << "\"Y\":" << Y << ","; - f << "\"Z\":" << Z; - f << "}"; - f << "}"; - if (vi < numVerts - 1) - { - f << ","; - } - } - - f << "]}"; - } - } - f << "],"; - f << R"("NavpJsonVersion": "0.1")"; - f << "}"; - f.close(); + const dtNavMesh* mesh = m_navMesh; + if (!mesh) return; + + remove(s_OutputFileName); + + std::ofstream f(s_OutputFileName); + f << std::fixed << std::boolalpha; + + f << R"({"NavpJsonVersion":"0.2","Sections":[{"NavGraphs":[{"Areas":[)"; + std::vector tilePolyCounts; + for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) { + const dtMeshTile* tile = mesh->getTile(tileIndex); + if (!tile || !tile->header || !tile->dataSize) { + tilePolyCounts.push_back(0); + continue; + } + tilePolyCounts.push_back(tile->header->polyCount); + } + int totalAreaCount = 0; + for (int count : tilePolyCounts) { + totalAreaCount += count; + } + std::vector allPolyflags; + int curPoly = 0; + std::vector indexToPolyInfo(totalAreaCount, {-1, -1}); + + for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) { + const dtMeshTile *tile = mesh->getTile(tileIndex); + if (!tile || !tile->header || !tile->dataSize) { + continue; + } + for (int polyIndex = 0; polyIndex < tile->header->polyCount; polyIndex++) { + allPolyflags.push_back(tile->polys[polyIndex].flags); + if (tile->polys[polyIndex].flags != SAMPLE_POLYFLAGS_DISABLED) { + const int totalIndex = getTotalIndex(tileIndex, polyIndex, tilePolyCounts); + indexToPolyInfo[totalIndex] = {tileIndex, polyIndex, curPoly++}; + } + } + } + curPoly = 0; + bool validAreaFound = false; + // Store tiles. + for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); ++tileIndex) + { + const dtMeshTile* tile = mesh->getTile(tileIndex); + if (!tile || !tile->header || !tile->dataSize) continue; + int numPolys = tile->header->polyCount; + for (int polyIndex = 0; polyIndex < numPolys; polyIndex++) { + const dtPoly& poly = tile->polys[polyIndex]; + + const int totalIndex = getTotalIndex(tileIndex, polyIndex, tilePolyCounts); + if (poly.flags == SAMPLE_POLYFLAGS_DISABLED) { + continue; + } + if (validAreaFound) { + f << ","; + } + if (!validAreaFound) { + validAreaFound = true; + } + f << "{"; + f << R"("Area":{"Index":)" << indexToPolyInfo[totalIndex].totalPolyIndex; + f << "},"; + f << "\"Edges\":["; + + int numVerts = poly.vertCount; + for (int vi = 0; vi < numVerts; vi++) { + unsigned short vertIndex = poly.verts[vi]; + float X = tile->verts[vertIndex * 3]; + float Y = -tile->verts[vertIndex * 3 + 2]; + float Z = tile->verts[vertIndex * 3 + 1]; + f << "{"; + for (unsigned int linkIndex = poly.firstLink; linkIndex != DT_NULL_LINK; linkIndex = tile->links[linkIndex].next) + { + const dtLink& link = tile->links[linkIndex]; + if (link.edge != vi) { + continue; + } + const dtMeshTile* targetTile = nullptr; + const dtPoly* targetPoly = nullptr; + mesh->getTileAndPolyByRef(link.ref, &targetTile, &targetPoly); + if (targetTile && targetPoly) + { + int targetTileIndex = -1; + for (int i = 0; i < mesh->getMaxTiles(); ++i) { + if (mesh->getTile(i) == targetTile) { + targetTileIndex = i; + break; + } + } + if (targetTileIndex != -1) { + int targetPolyIndex = -1; + for (int i = 0; i < targetTile->header->polyCount; ++i) { + if (&targetTile->polys[i] == targetPoly) { + targetPolyIndex = i; + break; + } + } + if (targetPolyIndex != -1) { + int neiTotalIndex = getTotalIndex(targetTileIndex, targetPolyIndex, tilePolyCounts); + if (neiTotalIndex < totalAreaCount && neiTotalIndex != -1) { + if (allPolyflags[neiTotalIndex] != SAMPLE_POLYFLAGS_DISABLED) { + f << "\"Adjacent Area\":"; + f << indexToPolyInfo[neiTotalIndex].totalPolyIndex + 1 << ","; + } + } + } + } + } + } + f << "\"Position\":"; + f << "{"; + f << "\"X\":" << X << ","; + f << "\"Y\":" << Y << ","; + f << "\"Z\":" << Z; + f << "}"; + f << "}"; + if (vi < numVerts - 1) + { + f << ","; + } + } + + f << "]}"; + } + } + f << "]}]}]}"; + f.close(); } diff --git a/src/model/Json.cpp b/src/model/Json.cpp index 2af930e..9fbc935 100644 --- a/src/model/Json.cpp +++ b/src/model/Json.cpp @@ -41,7 +41,7 @@ void Json::Vec3::readJson(simdjson::ondemand::object json) { } void Json::Vec3::writeJson(std::ostream& f, const std::string& propertyName) const { - f << R"(")" << propertyName << R"(":{"x":)" << x << R"(,"y":)" << y << R"(,"z": )" << z << "}"; + f << R"(")" << propertyName << R"(":{"x":)" << x << R"(,"y":)" << y << R"(,"z":)" << z << "}"; } void Json::Rotation::readJson(simdjson::ondemand::object json) { @@ -52,7 +52,7 @@ void Json::Rotation::readJson(simdjson::ondemand::object json) { } void Json::Rotation::writeJson(std::ostream& f) const { - f << R"("rotation":{"x":)" << x << R"(,"y":)" << y << R"(,"z": )" << z << R"(,"w": )" << w << "}"; + f << R"("rotation":{"x":)" << x << R"(,"y":)" << y << R"(,"z":)" << z << R"(,"w":)" << w << "}"; } void Json::PfBoxType::readJson(simdjson::ondemand::object json) { @@ -72,7 +72,7 @@ void Json::Vec3Wrapped::readJson(simdjson::ondemand::object json) { void Json::Vec3Wrapped::writeJson(std::ostream& f, std::string propertyName) const { f << R"(")" << propertyName << R"(":{"type":")" << type << R"(","data":{"x":)" << data.x << R"(,"y":)" << data.y << - R"(,"z": )" << data.z << + R"(,"z":)" << data.z << "}}"; } @@ -124,7 +124,7 @@ void Json::Mesh::writeJson(std::ostream& f) const { R"(","roomName":")" << roomName << R"(","roomFolderName":")" << roomFolderName << R"(","entity":{"id":")" << entity.id << - R"(","name":")" << entity.name; + R"(","name":")" << entity.name << R"(",)"; entity.position.writeJson(f); f << ","; entity.rotation.writeJson(f); diff --git a/src/module/Airg.cpp b/src/module/Airg.cpp index 489c32e..49535e5 100644 --- a/src/module/Airg.cpp +++ b/src/module/Airg.cpp @@ -284,7 +284,7 @@ bool Airg::canBuildAirg() const { } void Airg::handleBuildAirgClicked() { - if (const Navp& navp = Navp::getInstance(); navp.navMesh->m_areas.size() > 65535) { + if (const Navp& navp = Navp::getInstance(); Navp::getTotalAreaCount(navp.navMesh) > 65535) { Logger::log( NK_ERROR, "Loaded NAVP has too many areas. Ensure the scene has PF Seed Points and has a fully contained boundary."); @@ -381,18 +381,20 @@ void Airg::addWaypointGeometry(std::vector& triVerts, std::vector / 4.0f; if (selected || forceFan) { for (int i = 0; i < 8; i++) { - const float a1 = static_cast(i) / 8.0f * std::numbers::pi * 2; - const float a2 = static_cast(i + 1) / 8.0f * std::numbers::pi * 2; + const float a1 = static_cast(i) * step; + const float a2 = static_cast(i + 1) * step; const glm::vec3 p1(waypoint.vPos.x + cosf(a1) * r, z, -(waypoint.vPos.y + sinf(a1) * r)); const glm::vec3 p2(waypoint.vPos.x + cosf(a2) * r, z, -(waypoint.vPos.y + sinf(a2) * r)); - triVerts.push_back({center, glm::vec3(0, 1, 0), color}); - triVerts.push_back({p1, glm::vec3(0, 1, 0), color}); - triVerts.push_back({p2, glm::vec3(0, 1, 0), color}); + triVerts.push_back({center, normal, color}); + triVerts.push_back({p2, normal, color}); + triVerts.push_back({p1, normal, color}); } } else { // Line Loop @@ -641,8 +643,8 @@ void Airg::renderAirgForHitTest() const { for (size_t i = 0; i < numWaypoints; i++) { const Waypoint& waypoint = reasoningGrid->m_WaypointList[i]; const float r = static_cast(AIRG_WAYPOINT) / 255.0f; - const float g = static_cast(i / 255) / 255.0f; - const float b = static_cast(i % 255) / 255.0f; + const float g = static_cast(i >> 8 & 0xFF) / 255.0f; + const float b = static_cast(i & 0xFF) / 255.0f; glm::vec4 color(r, g, b, 1.0f); addWaypointGeometry(triVerts, lineVerts, waypoint, true, color, true); } @@ -694,7 +696,7 @@ void Airg::setSelectedAirgWaypointIndex(const int index) { selectedWaypointIndex = index; if (index != -1 && index < reasoningGrid->m_WaypointList.size()) { const Waypoint waypoint = reasoningGrid->m_WaypointList[index]; - std::string msg = "Airg Waypoint " + std::to_string(index); + std::string msg = "Selected Airg Waypoint " + std::to_string(index); for (int i = 0; i < waypoint.nNeighbors.size(); i++) { const int neighborIndex = waypoint.nNeighbors[i]; if (neighborIndex != 65535) { diff --git a/src/module/InputHandler.cpp b/src/module/InputHandler.cpp index 2cc0416..57c25be 100644 --- a/src/module/InputHandler.cpp +++ b/src/module/InputHandler.cpp @@ -101,7 +101,7 @@ int InputHandler::handleInput() { case SDL_MOUSEMOTION: mousePos[0] = event.motion.x; - mousePos[1] = renderer.height - 1 - event.motion.y; + mousePos[1] = renderer.height - event.motion.y - MENU_HEIGHT; if (rotate) { const auto dx = static_cast(mousePos[0] - origMousePos[0]); diff --git a/src/module/Navp.cpp b/src/module/Navp.cpp index df99232..04f061c 100644 --- a/src/module/Navp.cpp +++ b/src/module/Navp.cpp @@ -84,27 +84,26 @@ void Navp::updateNavMeshBuffers(const NavPower::NavMesh* navMesh, int selectedIn std::vector triVertices; std::vector lineVertices; - for (int i = 0; i < navMesh->m_areas.size(); ++i) { - const auto& area = navMesh->m_areas[i]; + for (int i = 0; i < getTotalAreaCount(navMesh); ++i) { + const auto& [area, edges] = getAreaByIndex(navMesh, i); bool selected = (i == selectedIndex); // Determine Area Color glm::vec4 areaColor; - bool isStairs = area.m_area->m_usageFlags == NavPower::AreaUsageFlags::AREA_STEPS; - if (isStairs) { + if (area->m_usageFlags == NavPower::AreaUsageFlags::AREA_STEPS) { areaColor = selected ? glm::vec4(1.0, 1.0, 0.5, 1.0) : glm::vec4(0.5, 0.5, 0.0, 1.0); } else { areaColor = selected ? glm::vec4(0.0, 0.9, 0.0, 1.0) : glm::vec4(0.0, 0.5, 0.0, 1.0); } // Triangulate (Fan) - if (area.m_edges.size() >= 3) { - const auto& v0 = area.m_edges[0]; + if (edges.size() >= 3) { + const auto& v0 = edges[0]; glm::vec3 p0(v0->m_pos.X, v0->m_pos.Z, -v0->m_pos.Y); - for (size_t j = 1; j < area.m_edges.size() - 1; ++j) { - const auto& v1 = area.m_edges[j]; - const auto& v2 = area.m_edges[j + 1]; + for (size_t j = 1; j < edges.size() - 1; ++j) { + const auto& v1 = edges[j]; + const auto& v2 = edges[j + 1]; glm::vec3 p1(v1->m_pos.X, v1->m_pos.Z, -v1->m_pos.Y); glm::vec3 p2(v2->m_pos.X, v2->m_pos.Z, -v2->m_pos.Y); @@ -116,9 +115,9 @@ void Navp::updateNavMeshBuffers(const NavPower::NavMesh* navMesh, int selectedIn } // Lines - for (size_t j = 0; j < area.m_edges.size(); ++j) { - auto vStart = area.m_edges[j]; - auto vEnd = area.m_edges[(j + 1) % area.m_edges.size()]; + for (size_t j = 0; j < edges.size(); ++j) { + auto vStart = edges[j]; + auto vEnd = edges[(j + 1) % edges.size()]; glm::vec3 pStart(vStart->m_pos.X, vStart->m_pos.Z + 0.01f, -vStart->m_pos.Y); glm::vec3 pEnd(vEnd->m_pos.X, vEnd->m_pos.Z + 0.01f, -vEnd->m_pos.Y); @@ -135,7 +134,7 @@ void Navp::updateNavMeshBuffers(const NavPower::NavMesh* navMesh, int selectedIn } // Portal Loops (Circles) - for (auto vertex : area.m_edges) { + for (auto vertex : edges) { if (vertex->GetType() == NavPower::EdgeType::EDGE_PORTAL) { const float r = 0.05f; glm::vec4 circleColor(1.0, 1.0, 1.0, 1.0); @@ -199,27 +198,50 @@ void Navp::updateNavMeshBuffers(const NavPower::NavMesh* navMesh, int selectedIn glBindVertexArray(0); } +int Navp::getTotalAreaCount(const NavPower::NavMesh* navMesh) { + int areaCount = 0; + for (const auto& section : navMesh->m_aSections) { + for (const auto& navGraph : section.m_aNavGraphs) { + areaCount += navGraph.m_areas.size(); + } + } + return areaCount; +} + +NavPower::Area& Navp::getAreaByIndex(const NavPower::NavMesh* navMesh, const int index) { + int curAreaIndex = 0; + for (auto& section : const_cast(navMesh)->m_aSections) { + for (auto& navGraph : section.m_aNavGraphs) { + if (index < curAreaIndex + static_cast(navGraph.m_areas.size())) { + return navGraph.m_areas[index - curAreaIndex]; + } + curAreaIndex += navGraph.m_areas.size(); + } + } + throw std::runtime_error("Area index out of bounds"); +} + void Navp::updateHitTestBuffers(const NavPower::NavMesh* navMesh) { if (!navMesh) { return; } std::vector vertices; - for (int i = 0; i < navMesh->m_areas.size(); ++i) { - const auto& area = navMesh->m_areas[i]; + for (int i = 0; i < getTotalAreaCount(navMesh); ++i) { + const auto& [area, edges] = getAreaByIndex(navMesh, i); const float r = static_cast(NAVMESH_AREA) / 255.0f; - const float g = static_cast(i / 255) / 255.0f; - const float b = static_cast(i % 255) / 255.0f; + const float g = static_cast(i >> 8 & 0xFF) / 255.0f; + const float b = static_cast(i & 0xFF) / 255.0f; const glm::vec4 color(r, g, b, 1.0f); - if (area.m_edges.size() >= 3) { - const auto& v0 = area.m_edges[0]; + if (edges.size() >= 3) { + const auto& v0 = edges[0]; const glm::vec3 p0(v0->m_pos.X, v0->m_pos.Z, -v0->m_pos.Y); - for (size_t j = 1; j < area.m_edges.size() - 1; ++j) { - const auto& v1 = area.m_edges[j]; - const auto& v2 = area.m_edges[j + 1]; + for (size_t j = 1; j < edges.size() - 1; ++j) { + const auto& v1 = edges[j]; + const auto& v2 = edges[j + 1]; const glm::vec3 p1(v1->m_pos.X, v1->m_pos.Z, -v1->m_pos.Y); const glm::vec3 p2(v2->m_pos.X, v2->m_pos.Z, -v2->m_pos.Y); @@ -294,13 +316,13 @@ void Navp::renderPfSeedPointsForHitTest() const { {0, 0, 0, 1}, true, { - static_cast(PF_SEED_POINT) / 255.05f, static_cast(highByte) / 255.0f, - static_cast(lowByte) / 255.05f + static_cast(PF_SEED_POINT) / 255.0f, static_cast(highByte) / 255.0f, + static_cast(lowByte) / 255.0f }, true, { - static_cast(PF_SEED_POINT) / 255.05f, static_cast(highByte) / 255.0f, - static_cast(lowByte) / 255.05f + static_cast(PF_SEED_POINT) / 255.0f, static_cast(highByte) / 255.0f, + static_cast(lowByte) / 255.0f }, 1.0); i++; @@ -350,13 +372,13 @@ void Navp::renderExclusionBoxesForHitTest() const { {exclusionBox.rotation.x, exclusionBox.rotation.z, -exclusionBox.rotation.y, exclusionBox.rotation.w}, true, { - static_cast(PF_EXCLUSION_BOX) / 255.05f, static_cast(highByte) / 255.0f, - static_cast(lowByte) / 255.05f + static_cast(PF_EXCLUSION_BOX) / 255.0f, static_cast(highByte) / 255.0f, + static_cast(lowByte) / 255.0f }, true, { - static_cast(PF_EXCLUSION_BOX) / 255.05f, static_cast(highByte) / 255.0f, - static_cast(lowByte) / 255.05f + static_cast(PF_EXCLUSION_BOX) / 255.0f, static_cast(highByte) / 255.0f, + static_cast(lowByte) / 255.0f }, 1.0); i++; @@ -390,7 +412,8 @@ bool Navp::areaIsStairs(const NavPower::Area& area) { } void Navp::setStairsFlags() const { - for (auto& area : navMesh->m_areas) { + for (int i = 0; i < getTotalAreaCount(navMesh); ++i) { + auto& area = getAreaByIndex(navMesh, i); const Vec3 normal = area.CalculateNormal(); const Vec3 horizontalProjection = {normal.Y, 0.0f, normal.Z}; const float horizontalMagnitude = std::sqrt( @@ -414,8 +437,8 @@ void Navp::setSelectedNavpAreaIndex(const int index) { Logger::log(NK_INFO, ("Deselected area: " + std::to_string(selectedNavpAreaIndex + 1)).c_str()); } selectedNavpAreaIndex = index; - if (index != -1 && index < navMesh->m_areas.size()) { - auto& selectedArea = navMesh->m_areas[index]; + if (index != -1 && index < getTotalAreaCount(navMesh)) { + auto& selectedArea = getAreaByIndex(navMesh, index); Logger::log(NK_INFO, ("Selected area: " + std::to_string(index + 1)).c_str()); const Vec3 pos = selectedArea.m_area->m_pos; char v[16]; @@ -556,20 +579,23 @@ void Navp::renderNavMesh() { const Vec3 colorPink = {1.0f, .7f, 1.0f}; if (showNavpIndices) { int areaIndex = 0; - for (const NavPower::Area& area : navMesh->m_areas) { + for (int i = 0; i < getTotalAreaCount(navMesh); ++i) { + const auto& area = getAreaByIndex(navMesh, i); + const auto& edges = area.m_edges; + const Vec3 pos = area.m_area->m_pos; renderer.drawText(std::to_string(areaIndex + 1), { - area.m_area->m_pos.X, area.m_area->m_pos.Z + 0.1f, -area.m_area->m_pos.Y + pos.X, pos.Z + 0.1f, -pos.Y }, colorBlue, 20); if (selectedNavpAreaIndex == areaIndex) { int edgeIndex = 0; - for (const auto vertex : area.m_edges) { + for (const auto vertex : edges) { renderer.drawText(std::to_string(edgeIndex + 1), {vertex->m_pos.X, vertex->m_pos.Z + 0.1f, -vertex->m_pos.Y}, vertex->GetType() == NavPower::EdgeType::EDGE_PORTAL ? colorRed : colorGreen, 20); if (vertex->m_pAdjArea != nullptr) { - const auto nextVertex = area.m_edges[(edgeIndex + 1) % area.m_edges.size()]; + const auto nextVertex = edges[(edgeIndex + 1) % edges.size()]; Vec3 midpoint = (vertex->m_pos + nextVertex->m_pos) / 2.0f; const int neighborAreaIndex = binaryAreaToAreaIndexMap[vertex->m_pAdjArea]; renderer.drawText(std::to_string(neighborAreaIndex), @@ -651,15 +677,15 @@ void Navp::loadNavMesh(const std::string& fileName, const bool isFromJson, const OutputNavMesh_JSON_Write(navMesh, (outputNavpFilename + ".json").c_str()); NavPower::NavMesh reloadedNavMesh = LoadNavMeshFromJson((outputNavpFilename + ".json").c_str()); std::swap(*navMesh, reloadedNavMesh); - + } if (isFromJson) { OutputNavMesh_NAVP_Write(navMesh, outputNavpFilename.c_str()); loadNavMeshFileData(outputNavpFilename); - + }else { loadNavMeshFileData(fileName); - + } } CPPTRACE_CATCH(const std::exception & e) @@ -728,13 +754,13 @@ void Navp::buildNavp() { Logger::log(NK_INFO, msg.data()); setSelectedNavpAreaIndex(-1); Menu::updateMenuState(); - + }else { Logger::log(NK_ERROR, "Error building Navp"); building = false; navpBuildDone.store(false); Menu::updateMenuState(); - + } } CPPTRACE_CATCH(const std::exception & e) @@ -844,8 +870,8 @@ void Navp::handleSaveNavpClicked() { bool Navp::stairsAreaSelected() const { return selectedNavpAreaIndex == -1 ? false - : selectedNavpAreaIndex < navMesh->m_areas.size() - ? areaIsStairs(navMesh->m_areas[selectedNavpAreaIndex]) + : selectedNavpAreaIndex < getTotalAreaCount(navMesh) + ? areaIsStairs(getAreaByIndex(navMesh, selectedNavpAreaIndex)) : false; } @@ -863,16 +889,16 @@ bool Navp::canSave() const { void Navp::handleEditStairsClicked() const { if (selectedNavpAreaIndex != -1) { - const NavPower::AreaUsageFlags newType = (navMesh->m_areas[selectedNavpAreaIndex].m_area->m_usageFlags == + const NavPower::AreaUsageFlags newType = (getAreaByIndex(navMesh, selectedNavpAreaIndex).m_area->m_usageFlags == NavPower::AreaUsageFlags::AREA_STEPS) ? NavPower::AreaUsageFlags::AREA_FLAT : NavPower::AreaUsageFlags::AREA_STEPS; - const std::string newTypeString = (navMesh->m_areas[selectedNavpAreaIndex].m_area->m_usageFlags == + const std::string newTypeString = (getAreaByIndex(navMesh, selectedNavpAreaIndex).m_area->m_usageFlags == NavPower::AreaUsageFlags::AREA_STEPS) ? "AREA_FLAT" : "AREA_STEPS"; Logger::log(NK_INFO, ("Setting area type to: " + newTypeString).c_str()); - navMesh->m_areas[selectedNavpAreaIndex].m_area->m_usageFlags = newType; + getAreaByIndex(navMesh, selectedNavpAreaIndex).m_area->m_usageFlags = newType; navMeshDirty = true; Menu::updateMenuState(); } @@ -886,7 +912,8 @@ void Navp::buildAreaMaps() { binaryAreaToAreaMap.clear(); posToAreaMap.clear(); int areaIndex = 1; - for (NavPower::Area& area : navMesh->m_areas) { + for (int i = 0; i < getTotalAreaCount(navMesh); ++i) { + auto& area = getAreaByIndex(navMesh, i); binaryAreaToAreaIndexMap.emplace(area.m_area, areaIndex); binaryAreaToAreaMap.emplace(area.m_area, &area); posToAreaMap.emplace(area.m_area->m_pos, &area); diff --git a/src/module/Renderer.cpp b/src/module/Renderer.cpp index d1412ea..5b5b7a3 100644 --- a/src/module/Renderer.cpp +++ b/src/module/Renderer.cpp @@ -297,16 +297,8 @@ void Renderer::renderFrame() { if (const SceneMesh& obj = SceneMesh::getInstance(); obj.objLoaded && obj.showObj) { GLboolean blendEnabled; glGetBooleanv(GL_BLEND, &blendEnabled); - static bool blendLogged = false; - if (!blendLogged) { - Logger::log(NK_DEBUG, "Renderer::renderFrame: GL_BLEND is %s", blendEnabled ? "ENABLED" : "DISABLED"); - blendLogged = true; - } glEnable(GL_TEXTURE_2D); - // Note: If obj.renderObj() contains both the floor and the grease spot, - // applying the offset here moves both, which doesn't fix fighting between them. - // However, we'll keep a slight offset to prevent fighting with the grid. glPolygonOffset(-1.0f, -1.0f); obj.renderObj(); glPolygonOffset(0.0f, 0.0f); @@ -475,6 +467,8 @@ void Renderer::drawText(const std::string& text, const Vec3 pos, const Vec3 colo return; } + glUseProgram(0); + glPushMatrix(); glTranslatef(pos.X, pos.Y, pos.Z); @@ -619,9 +613,6 @@ void Renderer::drawBox(const Vec3 pos, const Vec3 size, const Math::Quaternion r glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); - // 1. Disable depth writing so transparent boxes don't "cut holes" in the floor - // 2. Increase offset units to -2.0 to be more aggressive against Z-fighting - glDepthMask(GL_FALSE); glPolygonOffset(-2.0f, -2.0f); if (filled && !filledVertices.empty()) { @@ -638,7 +629,6 @@ void Renderer::drawBox(const Vec3 pos, const Vec3 size, const Math::Quaternion r glDrawArrays(GL_LINES, 0, outlinedVertices.size() / 3); } - glDepthMask(GL_TRUE); glPolygonOffset(0.0f, 0.0f); glBindVertexArray(0); glUseProgram(0); @@ -653,35 +643,36 @@ HitTestResult Renderer::hitTestRender(const int mx, const int my) const { Logger::log(NK_ERROR, ("FB error, status: 0x" + std::to_string(static_cast(status))).c_str()); printf("FB error, status: 0x%x\n", status); - return HitTestResult(NONE, -1); + return {NONE, -1}; } Navp::getInstance().renderNavMeshForHitTest(); Navp::getInstance().renderPfSeedPointsForHitTest(); Navp::getInstance().renderExclusionBoxesForHitTest(); Airg::getInstance().renderAirgForHitTest(); - const SceneMesh& obj = SceneMesh::getInstance(); - if (obj.showObj && obj.objLoaded) { - obj.renderObj(); + const SceneMesh& sceneMesh = SceneMesh::getInstance(); + if (sceneMesh.showObj && sceneMesh.objLoaded) { + RecastAdapter::getInstance().renderRecastNavmesh(false); } GLubyte pixel[4]; glReadBuffer(GL_COLOR_ATTACHMENT0); glReadPixels(mx, my, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); glBindFramebuffer(GL_FRAMEBUFFER, 0); glUseProgram(0); - const int selectedIndex = static_cast(pixel[1]) * 255 + static_cast(pixel[2]); - if (selectedIndex == 65280) { - return HitTestResult(NONE, -1); + if (pixel[0] == 255) { + return {NONE, -1}; } + + const int selectedIndex = static_cast(pixel[1]) * 256 + static_cast(pixel[2]); HitTestType result = NONE; - if (static_cast(pixel[0]) == NAVMESH_AREA) { + if (pixel[0] == NAVMESH_AREA) { result = NAVMESH_AREA; - } else if (static_cast(pixel[0]) == AIRG_WAYPOINT) { + } else if (pixel[0] == AIRG_WAYPOINT) { result = AIRG_WAYPOINT; - } else if (static_cast(pixel[0]) == PF_SEED_POINT) { + } else if (pixel[0] == PF_SEED_POINT) { result = PF_SEED_POINT; - } else if (static_cast(pixel[0]) == PF_EXCLUSION_BOX) { + } else if (pixel[0] == PF_EXCLUSION_BOX) { result = PF_EXCLUSION_BOX; } - return HitTestResult(result, result != NONE ? selectedIndex : -1); + return {result, result != NONE ? selectedIndex : -1}; } diff --git a/src/module/Rpkg.cpp b/src/module/Rpkg.cpp index 5803d62..f4ee380 100644 --- a/src/module/Rpkg.cpp +++ b/src/module/Rpkg.cpp @@ -71,11 +71,6 @@ void Rpkg::initExtractionData() { Logger::log(NK_INFO, "Done reading filtered hash list."); }); - std::jthread hashListThread([]() { - Logger::log(NK_INFO, "Getting full hash list."); - getHashList(); - }); - partitionManager = scan_packages(retailFolder.c_str(), gameVersion.c_str(), Logger::rustLogCallback); extractionDataInitComplete = true; Logger::log(NK_INFO, "Done scanning resource packages."); @@ -104,45 +99,48 @@ void Rpkg::initExtractionData() { } }); + // Disabling for now since it's not actually used yet + // std::jthread hashListThread([]() { + // Logger::log(NK_INFO, "Getting full hash list."); + // getHashList(); + // }); + navpThread.join(); airgThread.join(); filteredHashListThread.join(); - hashListThread.join(); - - Logger::log(NK_INFO, "Loading hash list into memory."); - - RustStringList* hashListRustStringList = hash_list_get_all_hashes(hashList); - Logger::log(NK_INFO, "Total hash list entries: %d, adding entries...", hashListRustStringList->length); - - const int numThreads = std::thread::hardware_concurrency(); - const int entriesPerThread = (hashListRustStringList->length + numThreads - 1) / numThreads; - std::vector workers; - - for (int t = 0; t < numThreads; ++t) { - workers.emplace_back([t, entriesPerThread, hashListRustStringList]() { - const int start = t * entriesPerThread; - const int end = std::min(start + entriesPerThread, static_cast(hashListRustStringList->length)); - for (int i = start; i < end; i++) { - std::string hash = hashListRustStringList->entries[i]; - const char* pathCStr = hash_list_get_path_by_hash(hashList, hash.c_str()); - std::string path = pathCStr ? pathCStr : ""; - const char* hintCStr = hash_list_get_hint_by_hash(hashList, hash.c_str()); - std::string ioiString = hintCStr ? hintCStr : ""; - auto typeInt = hash_list_get_resource_type_by_hash(hashList, hash.c_str()); - char typeChars[4]; - std::memcpy(typeChars, &typeInt, sizeof(typeInt)); - std::string type(typeChars, sizeof(typeChars)); - - std::lock_guard lock(hashMapsMutex); - hashToHashListEntryMap.insert({hash, {hash, ioiString, type}}); - ioiStringToHashListEntryMap.insert({ioiString, {hash, ioiString, type}}); - } - }); - } - - workers.clear(); - - Logger::log(NK_INFO, "Done getting full hash list."); + // hashListThread.join(); + + // Logger::log(NK_INFO, "Loading hash list into memory."); + // RustStringList* hashListRustStringList = hash_list_get_all_hashes(hashList); + // Logger::log(NK_INFO, "Total hash list entries: %d, adding entries...", hashListRustStringList->length); + // + // const int numThreads = std::thread::hardware_concurrency(); + // const int entriesPerThread = (hashListRustStringList->length + numThreads - 1) / numThreads; + // std::vector workers; + // + // for (int t = 0; t < numThreads; ++t) { + // workers.emplace_back([t, entriesPerThread, hashListRustStringList]() { + // const int start = t * entriesPerThread; + // const int end = std::min(start + entriesPerThread, static_cast(hashListRustStringList->length)); + // for (int i = start; i < end; i++) { + // std::string hash = hashListRustStringList->entries[i]; + // const char* pathCStr = hash_list_get_path_by_hash(hashList, hash.c_str()); + // std::string path = pathCStr ? pathCStr : ""; + // const char* hintCStr = hash_list_get_hint_by_hash(hashList, hash.c_str()); + // std::string ioiString = hintCStr ? hintCStr : ""; + // auto typeInt = hash_list_get_resource_type_by_hash(hashList, hash.c_str()); + // char typeChars[4]; + // std::memcpy(typeChars, &typeInt, sizeof(typeInt)); + // std::string type(typeChars, sizeof(typeChars)); + // + // std::lock_guard lock(hashMapsMutex); + // hashToHashListEntryMap.insert({hash, {hash, ioiString, type}}); + // ioiStringToHashListEntryMap.insert({ioiString, {hash, ioiString, type}}); + // } + // }); + // } + // workers.clear(); + // Logger::log(NK_INFO, "Done getting full hash list."); Menu::updateMenuState(); } diff --git a/src/module/SceneMesh.cpp b/src/module/SceneMesh.cpp index ea86316..66d9a3b 100644 --- a/src/module/SceneMesh.cpp +++ b/src/module/SceneMesh.cpp @@ -223,17 +223,21 @@ void SceneMesh::buildObjFromNavp(const bool alsoLoadIntoUi) { std::vector> faces; std::map pointsToIndexMap; int pointCount = 1; - for (const auto& [m_area, m_edges] : navp.navMesh->m_areas) { - std::vector face; - for (const auto edge : m_edges) { - auto point = edge->m_pos; - if (!pointsToIndexMap.contains(point)) { - vertices.push_back(point); - pointsToIndexMap[point] = pointCount++; + for (auto section : navp.navMesh->m_aSections) { + for (auto navGraph : section.m_aNavGraphs) { + for (const auto& [m_area, m_edges] : navGraph.m_areas) { + std::vector face; + for (const auto edge : m_edges) { + auto point = edge->m_pos; + if (!pointsToIndexMap.contains(point)) { + vertices.push_back(point); + pointsToIndexMap[point] = pointCount++; + } + face.push_back(pointsToIndexMap[point]); + } + faces.push_back(face); } - face.push_back(pointsToIndexMap[point]); } - faces.push_back(face); } std::ofstream f(fileName); f.clear(); @@ -587,11 +591,7 @@ void SceneMesh::loadObjMesh() { } } else { modelFuture.wait(); - Logger::log(NK_ERROR, "Error loading obj."); - const RecastAdapter& recastAdapter = RecastAdapter::getInstance(); - if (recastAdapter.getVertCount() == 0) { - Logger::log(NK_ERROR, "Cannot load Obj, Obj has 0 vertices."); - } + Logger::log(NK_ERROR, "Error loading obj. Obj may have too many vertices or have 0 vertices."); model.meshes.clear(); SceneExtract::getInstance().alsoBuildAll = false; Menu::updateMenuState(); @@ -601,12 +601,6 @@ void SceneMesh::loadObjMesh() { void SceneMesh::renderObj() const { const Renderer& renderer = Renderer::getInstance(); - static int logCounterObj = 0; - if (logCounterObj < 10) { - Logger::log(NK_DEBUG, "SceneMesh::renderObj: meshes count: %zu, objLoaded: %d", model.meshes.size(), objLoaded); - logCounterObj++; - } - glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); diff --git a/src/render/Mesh.cpp b/src/render/Mesh.cpp index 9a19253..076af78 100644 --- a/src/render/Mesh.cpp +++ b/src/render/Mesh.cpp @@ -36,10 +36,6 @@ Mesh::Mesh(const std::vector& vertices, const std::vector& for (const auto& t : textures) { if (t.uploadFormat == GL_RGBA) { isTransparent = true; - // We assume RGBA textures might need blending, - // but the shader handles cutout with discard. - // If it's a known format or we could check the data, we'd be more sure. - // For now, let's treat RGBA as "could be transparent". break; } } @@ -65,30 +61,11 @@ void Mesh::draw(const Shader& shader) const { shader.setInt(name + number, static_cast(i)); glBindTexture(GL_TEXTURE_2D, textures[i].id); - - static int logCounterBind = 0; - if (logCounterBind < 10) { - Logger::log(NK_DEBUG, "Mesh::draw bind: unit=%d, name=%s, id=%u, valid=%d", i, (name + number).c_str(), - textures[i].id, glIsTexture(textures[i].id)); - logCounterBind++; - } } shader.setBool("useTexture", !textures.empty()); if (!textures.empty()) { - static int logCounterTex = 0; - if (logCounterTex < 10) { - Logger::log(NK_DEBUG, "Mesh::draw: using textures, count: %zu, useTexture: 1, useFlatColor: 0", - textures.size()); - logCounterTex++; - } shader.setBool("useFlatColor", false); - } else { - static int logCounterNoTex = 0; - if (logCounterNoTex < 10) { - Logger::log(NK_DEBUG, "Mesh::draw: no textures, useTexture: 0"); - logCounterNoTex++; - } } shader.use(); @@ -100,11 +77,6 @@ void Mesh::draw(const Shader& shader) const { } void Mesh::setupMesh() { - if (VAO != 0) { - Logger::log(NK_INFO, "Mesh::setupMesh: VAO is not null"); - return; - } - glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); diff --git a/src/render/Model.cpp b/src/render/Model.cpp index 1a11fcb..d886ea6 100644 --- a/src/render/Model.cpp +++ b/src/render/Model.cpp @@ -59,11 +59,8 @@ Texture loadTextureDataFromFile(const char* path, const std::string& directory) texture.loaded = true; stbi_image_free(data); - Logger::log(NK_DEBUG, "Texture loaded successfully using stb_image: %s (%dx%d, %d channels)", - filename.c_str(), width, height, nrChannels); } else { - Logger::log(NK_ERROR, "Texture failed to load at path: %s. Reason: %s", - filename.c_str(), stbi_failure_reason()); + Logger::log(NK_ERROR, "Texture failed to load at path: %s. Reason: %s", filename.c_str(), stbi_failure_reason()); } return texture; @@ -102,14 +99,8 @@ Mesh Model::processBatchedMeshes(const std::vector& batch, const aiScen vec.x = mesh->mTextureCoords[0][i].x; vec.y = mesh->mTextureCoords[0][i].y; vertex.texCoords = vec; - if (i == 0) { - Logger::log(NK_DEBUG, "Mesh %s has UVs: %f, %f", mesh->mName.C_Str(), vec.x, vec.y); - } } else { vertex.texCoords = glm::vec2(0.0f, 0.0f); - if (i == 0) { - Logger::log(NK_DEBUG, "Mesh %s has NO UVs", mesh->mName.C_Str()); - } } if (mesh->HasVertexColors(0)) { @@ -200,8 +191,6 @@ void Model::loadModelData(std::string const& path) { directory = ""; } - Logger::log(NK_DEBUG, "Loading model: %s, base directory: %s", path.c_str(), directory.c_str()); - meshes.clear(); texturesLoaded.clear(); @@ -242,8 +231,6 @@ void Model::initGl() { texture.uploadFormat, GL_UNSIGNED_BYTE, texture.data.data()); glGenerateMipmap(GL_TEXTURE_2D); - Logger::log(NK_DEBUG, "Texture uploaded to GPU (ID:%u): %s", texture.id, texture.path.C_Str()); - texture.data.clear(); texture.data.shrink_to_fit(); } diff --git a/src/resource/fragment.glsl b/src/resource/fragment.glsl index 8d36da3..d1e54c5 100644 --- a/src/resource/fragment.glsl +++ b/src/resource/fragment.glsl @@ -21,7 +21,6 @@ void main() } else { FragColor = flatColor; } - FragColor.rgb *= 1.2; FragColor.a *= flatColor.a; return; } diff --git a/src/util/GridGenerator.cpp b/src/util/GridGenerator.cpp index 27a8c01..9410cd7 100644 --- a/src/util/GridGenerator.cpp +++ b/src/util/GridGenerator.cpp @@ -136,8 +136,18 @@ void GridGenerator::GenerateGrid() { void GridGenerator::GetGridProperties() { const Grid& grid = Grid::getInstance(); const Navp& navp = Navp::getInstance(); - Vec3 min = navp.navMesh->m_graphHdr->m_bbox.m_min; - const Vec3 max = navp.navMesh->m_graphHdr->m_bbox.m_max; + Vec3 min{10000.0f, 10000.0f, 10000.0f}; + Vec3 max{-10000.0f, -10000.0f, -10000.0f}; + for (const auto section : navp.navMesh->m_aSections) { + for (const auto navGraph : section.m_aNavGraphs) { + min.X = std::min(min.X, navGraph.m_hdr->m_bbox.m_min.X); + min.Y = std::min(min.Y, navGraph.m_hdr->m_bbox.m_min.Y); + min.Z = std::min(min.Z, navGraph.m_hdr->m_bbox.m_min.Z); + max.X = std::min(max.X, navGraph.m_hdr->m_bbox.m_max.X); + max.Y = std::min(max.Y, navGraph.m_hdr->m_bbox.m_max.Y); + max.Z = std::min(max.Z, navGraph.m_hdr->m_bbox.m_max.Z); + } + } min.X += grid.xOffset; min.Y += grid.yOffset; const int gridXSize = std::ceil((max.X - min.X) / grid.spacing); @@ -166,7 +176,7 @@ void GridGenerator::GenerateWaypointNodes() { const float invSpacing = 1.0f / spacing; waypointCells.clear(); - const int areaCount = navMesh->m_areas.size(); + const int areaCount = Navp::getTotalAreaCount(navMesh); const unsigned int num_threads = std::max(1u, std::thread::hardware_concurrency()); std::vector threads; std::mutex waypointCellsMutex; @@ -186,7 +196,7 @@ void GridGenerator::GenerateWaypointNodes() { Logger::log(NK_INFO, "[Thread %d] Progress: %d / %d areas processed...", thread_id, current_total_processed, areaCount); } - auto& area = navMesh->m_areas[areaIndex]; + NavPower::Area area = Navp::getAreaByIndex(navMesh, areaIndex); auto [m_min, m_max] = Pathfinding::calculateBBox(&area); const Vec3 normal = area.CalculateNormal(); const Vec3& v1 = {area.m_edges[0]->m_pos.X, area.m_edges[0]->m_pos.Y, area.m_edges[0]->m_pos.Z};