diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index 6c917b870..5a4f4d5c9 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -290,8 +290,8 @@ void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAAB atUint32 children[8]; for (int i = 0; i < 8; ++i) { /* Head recursion (first node will be a leaf) */ - children[i] = path.octree.size(); childNodes[i].pathWrite(path, SplitAABB(curAABB, i)); + children[i] = path.octree.size() - 1; } path.octree.emplace_back(); diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp index 577660e2f..d0403fc3e 100644 --- a/DataSpec/DNAMP1/PATH.cpp +++ b/DataSpec/DNAMP1/PATH.cpp @@ -5,6 +5,25 @@ namespace DataSpec::DNAMP1 { +#define DUMP_OCTREE 0 + +#if DUMP_OCTREE +/* octree dumper */ +static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) { + const zeus::CVector3f pos = aabb.center(); + const zeus::CVector3f extent = aabb.extents(); + os.format( + "obj = bpy.data.objects.new('Leaf_%d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_draw_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", idx, + pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); +} +#endif + void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf) { /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); @@ -85,7 +104,7 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry r.meshIndexMask, r.meshTypeMask, r.height); #if 0 - zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); + const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1])); os.format("aabb = bpy.data.objects.new('AABB', None)\n" "aabb.location = (%f,%f,%f)\n" @@ -95,13 +114,13 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry "centr = bpy.data.objects.new('Center', None)\n" "centr.location = (%f,%f,%f)\n" "bpy.context.scene.objects.link(centr)\n", - aabb.min.v[0] + (aabb.max.v[0] - aabb.min.v[0]) / 2.f, - aabb.min.v[1] + (aabb.max.v[1] - aabb.min.v[1]) / 2.f, - aabb.min.v[2] + (aabb.max.v[2] - aabb.min.v[2]) / 2.f, - (aabb.max.v[0] - aabb.min.v[0]) / 2.f, - (aabb.max.v[1] - aabb.min.v[1]) / 2.f, - (aabb.max.v[2] - aabb.min.v[2]) / 2.f, - center.x, center.y, center.z); + aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, + aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, + aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, + (aabb.max[0] - aabb.min[0]) / 2.f, + (aabb.max[1] - aabb.min[1]) / 2.f, + (aabb.max[2] - aabb.min[2]) / 2.f, + center.x(), center.y(), center.z()); #endif } @@ -151,6 +170,17 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); } +#if DUMP_OCTREE + { + int idx = 0; + for (const auto& n : octree) { + if (n.isLeaf) + OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1])); + ++idx; + } + } +#endif + os.linkBackground("//!area.blend"); os.centerView(); os.close(); @@ -170,7 +200,8 @@ bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: return conn.saveBlend(); } -bool PATH::Cook(const hecl::ProjectPath& outPath, const PathMesh& mesh) { +bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const PathMesh& mesh, hecl::blender::Token& btok) { athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); PATH path; path.read(r); @@ -188,6 +219,18 @@ bool PATH::Cook(const hecl::ProjectPath& outPath, const PathMesh& mesh) { n.children[i] = 0xffffffff; } +#if DUMP_OCTREE + { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh)) + return false; + + zeus::CMatrix4f xf; + path.sendToBlender(conn, "PATH"sv, &xf); + conn.saveBlend(); + } +#endif + athena::io::FileWriter w(outPath.getAbsolutePath()); path.write(w); int64_t rem = w.position() % 32; diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index de4229422..a6bc79f78 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -72,6 +72,7 @@ struct PATH : BigDNA { PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, std::function fileChanged); - static bool Cook(const hecl::ProjectPath& outPath, const PathMesh& mesh); + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const PathMesh& mesh, hecl::blender::Token& btok); }; } // namespace DataSpec::DNAMP1 diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 5826335ab..a94c22363 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -676,7 +676,7 @@ struct SpecMP1 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAMP1::PATH::Cook(out, mesh); + DNAMP1::PATH::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index a0981c204..a96a8c485 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -481,18 +481,19 @@ void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateMa float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleLeft, input); float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleRight, input); + float dirs[4] = {}; bool mouseHeld = false; if (const auto& kbm = input.GetKBM()) { - if (kbm->m_mouseButtons[int(boo::EMouseButton::Middle)]) { + if (kbm->m_mouseButtons[int(boo::EMouseButton::Primary)]) { mouseHeld = true; if (float(m_mouseDelta.x()) < 0.f) - right += -m_mouseDelta.x(); + dirs[3] = -m_mouseDelta.x(); else if (float(m_mouseDelta.x()) > 0.f) - left += m_mouseDelta.x(); + dirs[2] = m_mouseDelta.x(); if (float(m_mouseDelta.y()) < 0.f) - up += -m_mouseDelta.y(); + dirs[0] = -m_mouseDelta.y(); else if (float(m_mouseDelta.y()) > 0.f) - down += m_mouseDelta.y(); + dirs[1] = m_mouseDelta.y(); } } @@ -511,8 +512,7 @@ void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateMa dirSlot = 3; } - float dirs[4] = {}; - dirs[dirSlot] = maxMag; + dirs[dirSlot] += maxMag; if (dirs[0] > 0.f || dirs[1] > 0.f || dirs[2] > 0.f || dirs[3] > 0.f || mouseHeld) { int flags = 0x0; @@ -596,14 +596,17 @@ void CAutoMapper::ProcessMapZoomInput(const CFinalInput& input, const CStateMana bool in = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomIn, input); bool out = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomOut, input); + float zoomSpeed = 1.f; if (const auto& kbm = input.GetKBM()) { m_mapScroll += kbm->m_accumScroll - m_lastAccumScroll; m_lastAccumScroll = kbm->m_accumScroll; if (m_mapScroll.delta[1] > 0.0) { in = true; + zoomSpeed = std::max(1.f, float(m_mapScroll.delta[1])); m_mapScroll.delta[1] = std::max(0.0, m_mapScroll.delta[1] - (15.0 / 60.0)); } else if (m_mapScroll.delta[1] < 0.0) { out = true; + zoomSpeed = std::max(1.f, float(-m_mapScroll.delta[1])); m_mapScroll.delta[1] = std::min(0.0, m_mapScroll.delta[1] + (15.0 / 60.0)); } } @@ -634,7 +637,7 @@ void CAutoMapper::ProcessMapZoomInput(const CFinalInput& input, const CStateMana x324_zoomState = nextZoomState; float delta = input.DeltaTime() * 60.f * (x1bc_state == EAutoMapperState::MapScreen ? 1.f : 4.f) * - g_tweakAutoMapper->GetCamZoomUnitsPerFrame(); + g_tweakAutoMapper->GetCamZoomUnitsPerFrame() * zoomSpeed; float oldDist = xa8_renderStates[0].x18_camDist; if (x324_zoomState == EZoomState::In) { xa8_renderStates[0].x18_camDist = GetClampedMapScreenCameraDistance(xa8_renderStates[0].x18_camDist - delta); @@ -646,6 +649,8 @@ void CAutoMapper::ProcessMapZoomInput(const CFinalInput& input, const CStateMana x324_zoomState = EZoomState::Out; } + if (oldDist == xa8_renderStates[0].x18_camDist) + m_mapScroll.delta[1] = 0.0; SetShouldZoomingSoundBePlaying(oldDist != xa8_renderStates[0].x18_camDist); } @@ -657,7 +662,8 @@ void CAutoMapper::ProcessMapPanInput(const CFinalInput& input, const CStateManag bool mouseHeld = false; if (const auto& kbm = input.GetKBM()) { - if (kbm->m_mouseButtons[int(boo::EMouseButton::Primary)]) { + if (kbm->m_mouseButtons[int(boo::EMouseButton::Middle)] || + kbm->m_mouseButtons[int(boo::EMouseButton::Secondary)]) { mouseHeld = true; if (float(m_mouseDelta.x()) < 0.f) right += -m_mouseDelta.x(); diff --git a/Runtime/AutoMapper/CMapWorld.cpp b/Runtime/AutoMapper/CMapWorld.cpp index 7f6f612ad..230f472de 100644 --- a/Runtime/AutoMapper/CMapWorld.cpp +++ b/Runtime/AutoMapper/CMapWorld.cpp @@ -421,14 +421,14 @@ static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, return intersect <= 0.f; } -static Circle2 UpdateSupport1(int idx, zeus::CVector2f** list, Support& support) { +static Circle2 UpdateSupport1(int idx, const zeus::CVector2f** list, Support& support) { Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]); support.x0_ = 2; support.x4_[1] = idx; return ret; } -static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support) { +static Circle2 UpdateSupport2(int idx, const zeus::CVector2f** list, Support& support) { Circle2 circs[3] = {}; float intersect; int circIdx = -1; @@ -441,12 +441,11 @@ static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support) } circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); - if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[1]], circs[1], intersect)) { - minRad = circs[1].x8_radiusSq; + if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { circIdx = 1; } - Circle2 ret = {}; + Circle2 ret; if (circIdx != -1) { ret = circs[circIdx]; support.x4_[1 - circIdx] = idx; @@ -458,7 +457,7 @@ static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support) return ret; } -static Circle2 UpdateSupport3(int idx, zeus::CVector2f** list, Support& support) { +static Circle2 UpdateSupport3(int idx, const zeus::CVector2f** list, Support& support) { Circle2 circs[6] = {}; float intersect; int circIdxA = -1; @@ -576,15 +575,15 @@ static Circle2 UpdateSupport3(int idx, zeus::CVector2f** list, Support& support) return circs[circIdxA]; } -typedef Circle2 (*FSupport)(int idx, zeus::CVector2f** list, Support& support); +typedef Circle2 (*FSupport)(int idx, const zeus::CVector2f** list, Support& support); static const FSupport SupportFuncs[] = {nullptr, UpdateSupport1, UpdateSupport2, UpdateSupport3}; static Circle MinCircle(const std::vector& coords) { Circle2 ret = {}; if (coords.size() >= 1) { - std::unique_ptr randArr(new zeus::CVector2f*[coords.size()]); + std::unique_ptr randArr(new const zeus::CVector2f*[coords.size()]); for (int i = 0; i < coords.size(); ++i) - randArr[i] = const_cast(&coords[i]); + randArr[i] = &coords[i]; for (int i = coords.size() - 1; i >= 0; --i) { int shuf = rand() % (i + 1); if (shuf != i) diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index f46d84ee5..f30f413ef 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -158,7 +158,8 @@ void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { m_lastMouseCoord = mouseCoord; mouseDelta.x() *= g_Viewport.aspect; mouseDelta *= 100.f; - if (kbm->m_mouseButtons[int(boo::EMouseButton::Primary)]) { + if (kbm->m_mouseButtons[int(boo::EMouseButton::Middle)] || + kbm->m_mouseButtons[int(boo::EMouseButton::Secondary)]) { if (float(mouseDelta.x()) < 0.f) moveRight += -mouseDelta.x(); else if (float(mouseDelta.x()) > 0.f) @@ -168,7 +169,7 @@ void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { else if (float(mouseDelta.y()) > 0.f) moveBack += mouseDelta.y(); } - if (kbm->m_mouseButtons[int(boo::EMouseButton::Middle)]) { + if (kbm->m_mouseButtons[int(boo::EMouseButton::Primary)]) { if (float(mouseDelta.x()) < 0.f) circleRight += -mouseDelta.x(); else if (float(mouseDelta.x()) > 0.f) diff --git a/Runtime/World/CPathFindArea.cpp b/Runtime/World/CPathFindArea.cpp index e480170b5..c357aaca4 100644 --- a/Runtime/World/CPathFindArea.cpp +++ b/Runtime/World/CPathFindArea.cpp @@ -204,7 +204,7 @@ CPFRegion* CPFArea::FindClosestRegion(const zeus::CVector3f& point, u32 flags, u CPFRegion* ret = nullptr; for (rstl::prereserved_vector* list : regionListList) { for (CPFRegion* region : *list) { - if (region->Data()->GetCookie() != x34_curCookie) { + if (region->Data()->GetCookie() != x34_regionFindCookie) { if (region->GetFlags() & 0xff & flags && (region->GetFlags() >> 16) & 0xff & indexMask && region->IsPointInsidePaddedAABox(point, padding) && (isFlyer || region->PointHeight(point) < 3.f)) { if (region->FindBestPoint(x10_tmpPolyPoints, point, flags, padding * padding)) { @@ -215,10 +215,11 @@ CPFRegion* CPFArea::FindClosestRegion(const zeus::CVector3f& point, u32 flags, u x4_closestPoint = region->Data()->GetBestPoint(); } } - region->Data()->SetCookie(x34_curCookie); + region->Data()->SetCookie(x34_regionFindCookie); } } } + ++x34_regionFindCookie; return ret; } diff --git a/Runtime/World/CPathFindArea.hpp b/Runtime/World/CPathFindArea.hpp index 06b4f2454..d844566d3 100644 --- a/Runtime/World/CPathFindArea.hpp +++ b/Runtime/World/CPathFindArea.hpp @@ -67,7 +67,7 @@ class CPFArea { rstl::prereserved_vector* x20_cachedRegionList = nullptr; zeus::CVector3f x24_cachedRegionListPoint; bool x30_hasCachedRegionList = false; - s32 x34_curCookie = 0; + s32 x34_regionFindCookie = 0; CPFBitSet x38_closedSet; CPFOpenList x78_openList; // u32 x138_;