From 39ecb1e9a8de21a48eb12d28d83d3f4a8c1cc77b Mon Sep 17 00:00:00 2001
From: Deamon87 <dmitolm@gmail.com>
Date: Sat, 11 Mar 2023 13:33:34 +0200
Subject: [PATCH 1/4] add ability to load from filesystem

---
 3rdparty/DBImporter                      |  2 +-
 src/persistance/CascRequestProcessor.cpp | 38 +++++++++++++++++++++++-
 src/persistance/CascRequestProcessor.h   |  1 +
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/3rdparty/DBImporter b/3rdparty/DBImporter
index a4a1d8713..51678fdff 160000
--- a/3rdparty/DBImporter
+++ b/3rdparty/DBImporter
@@ -1 +1 @@
-Subproject commit a4a1d8713e23ae7391f6dc8dd409fea6f4d8a941
+Subproject commit 51678fdff7292747f089b5b207fb0b658927142b
diff --git a/src/persistance/CascRequestProcessor.cpp b/src/persistance/CascRequestProcessor.cpp
index 50210aa93..8e90def29 100644
--- a/src/persistance/CascRequestProcessor.cpp
+++ b/src/persistance/CascRequestProcessor.cpp
@@ -4,6 +4,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <iterator>
 #include "CascRequestProcessor.h"
 #include "../../3rdparty/casclib/src/CascLib.h"
 #include "../../3rdparty/filesystem_impl/include/ghc/filesystem.hpp"
@@ -132,6 +133,38 @@ HFileContent CascRequestProcessor::tryGetFile(void *cascStorage, void *fileNameT
     return fileContent;
 }
 
+static const std::string cacheDirectory = "./file_edits/";
+HFileContent CascRequestProcessor::tryGetFileFromOverrides(int fileDataId) {
+
+    std::string inputFileName = cacheDirectory + std::to_string(fileDataId);
+    std::ifstream cache_file(inputFileName, std::ios::in |std::ios::binary);
+    if (cache_file.good()) {
+        cache_file.unsetf(std::ios::skipws);
+
+        // get its size:
+        std::streampos fileSize;
+
+        cache_file.seekg(0, std::ios::end);
+        fileSize = cache_file.tellg();
+        cache_file.seekg(0, std::ios::beg);
+
+
+        HFileContent vec = std::make_shared<FileContent>(fileSize);
+        cache_file.read((char *) vec->data(), fileSize);
+
+        // read the data:
+        std::copy(std::istream_iterator<unsigned char>(cache_file),
+                  std::istream_iterator<unsigned char>(),
+                  std::back_inserter(*vec.get()));
+
+        std::cout << "Loaded fdid = " << fileDataId << " from " << inputFileName << std::endl;
+
+        return vec;
+    }
+    return nullptr;
+}
+
+
 void CascRequestProcessor::processFileRequest(std::string &fileName, CacheHolderType holderType, std::weak_ptr<PersistentFile> s_file) {
     auto perstFile = s_file.lock();
     uint32_t fileDataId = 0;
@@ -166,7 +199,9 @@ void CascRequestProcessor::processFileRequest(std::string &fileName, CacheHolder
     openFlags |= CASC_OVERCOME_ENCRYPTED;
 
     HFileContent fileContent;
-    if (this->m_storage != nullptr) {
+
+    fileContent = this->tryGetFileFromOverrides(fileDataId);
+    if (this->m_storage != nullptr && fileContent == nullptr) {
         fileContent = this->tryGetFile(this->m_storage, fileNameToPass, openFlags);
         if (fileContent == nullptr) {
             if (fileDataId > 0) {
@@ -207,3 +242,4 @@ CascRequestProcessor::~CascRequestProcessor() {
     if (m_storageOnline != nullptr)
         CascCloseStorage(m_storageOnline);
 }
+
diff --git a/src/persistance/CascRequestProcessor.h b/src/persistance/CascRequestProcessor.h
index 20a0e36df..5bc1b97fb 100644
--- a/src/persistance/CascRequestProcessor.h
+++ b/src/persistance/CascRequestProcessor.h
@@ -23,6 +23,7 @@ class CascRequestProcessor : public RequestProcessor {
     void processFileRequest(std::string &fileName, CacheHolderType holderType, std::weak_ptr<PersistentFile> s_file) override;
 private:
     HFileContent tryGetFile(void *cascStorage, void *fileNameToPass, uint32_t openFlags);
+    HFileContent tryGetFileFromOverrides(int fileDataId);
 };
 
 

From cbdad8cf9a94624ef559ce26cbf91666f1cc4b54 Mon Sep 17 00:00:00 2001
From: Deamon87 <dmitolm@gmail.com>
Date: Thu, 13 Apr 2023 03:46:13 +0300
Subject: [PATCH 2/4] fix portal culling on MSVC

---
 wowViewerLib/shaders/glsl/vulkan/ffxgauss4.frag    |  8 ++++----
 wowViewerLib/src/engine/algorithms/grahamScan.cpp  |  4 ++--
 wowViewerLib/src/engine/algorithms/mathHelper.cpp  | 12 +++++++++---
 wowViewerLib/src/engine/objects/scenes/map.cpp     |  2 +-
 wowViewerLib/src/engine/shader/ShaderDefinitions.h |  4 ++--
 wowViewerLib/src/gapi/vulkan/GDeviceVulkan.cpp     | 14 ++++++++++----
 wowViewerLib/src/gapi/vulkan/GDeviceVulkan.h       |  5 +++++
 7 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/wowViewerLib/shaders/glsl/vulkan/ffxgauss4.frag b/wowViewerLib/shaders/glsl/vulkan/ffxgauss4.frag
index a37e3d628..523ac8bef 100644
--- a/wowViewerLib/shaders/glsl/vulkan/ffxgauss4.frag
+++ b/wowViewerLib/shaders/glsl/vulkan/ffxgauss4.frag
@@ -19,10 +19,10 @@ const float weight[5] = float[] (0,  0.125, 0.375, 0.375, 0.125);
 void main()
 {
     // receive the soze of one texel
-//    vec2 tex_offset = 1.0 / textureSize(texture0, 0);
+    vec2 tex_offset = 1.0 / textureSize(texture0, 0);
     // the value of one fragmentslerp
-    vec2 tex_offset = vec2(0.001,0.001);
-    vec3 result = texture(texture0, texCoord).rgb * weight[0];
+//    vec2 tex_offset = vec2(0.001,0.001);
+//    vec3 result = texture(texture0, texCoord).rgb * weight[0];
 //    bool horizontal = textureDims.x > 0;
 //    if(horizontal)
 //    {
@@ -42,7 +42,7 @@ void main()
 //    }
 //    out_result = vec4(result, 1.0);
 
-    result = vec3(0.0);
+    vec3 result = vec3(0.0);
     result += texture(texture0, texCoord + vec2(texOffsetX.x*tex_offset.x, texOffsetY.x*tex_offset.y)).rgb * weight[1];
     result += texture(texture0, texCoord + vec2(texOffsetX.y*tex_offset.x, texOffsetY.y*tex_offset.y)).rgb * weight[2];
     result += texture(texture0, texCoord + vec2(texOffsetX.z*tex_offset.x, texOffsetY.z*tex_offset.y)).rgb * weight[3];
diff --git a/wowViewerLib/src/engine/algorithms/grahamScan.cpp b/wowViewerLib/src/engine/algorithms/grahamScan.cpp
index e22e610cd..6955fb543 100644
--- a/wowViewerLib/src/engine/algorithms/grahamScan.cpp
+++ b/wowViewerLib/src/engine/algorithms/grahamScan.cpp
@@ -43,7 +43,7 @@ void swap(Point &p1, Point &p2)
 
 // A utility function to return square of distance
 // between p1 and p2
-int distSq(Point p1, Point p2)
+int distSq(Point &p1, Point &p2)
 {
     return (p1.x - p2.x)*(p1.x - p2.x) +
            (p1.y - p2.y)*(p1.y - p2.y);
@@ -54,7 +54,7 @@ int distSq(Point p1, Point p2)
 // 0 --> p, q and r are colinear
 // 1 --> Clockwise
 // 2 --> Counterclockwise
-int orientation(Point p, Point q, Point r)
+int orientation(Point &p, Point &q, Point &r)
 {
     int val = (q.y - p.y) * (r.x - q.x) -
               (q.x - p.x) * (r.y - q.y);
diff --git a/wowViewerLib/src/engine/algorithms/mathHelper.cpp b/wowViewerLib/src/engine/algorithms/mathHelper.cpp
index f43e78b5b..149abf7a4 100644
--- a/wowViewerLib/src/engine/algorithms/mathHelper.cpp
+++ b/wowViewerLib/src/engine/algorithms/mathHelper.cpp
@@ -181,9 +181,15 @@ std::vector<mathfu::vec3> MathHelper::getHullPoints(std::vector<mathfu::vec3> &p
         return std::vector<mathfu::vec3>(0);
     }
 
-    mathfu::vec3* end   = &hullPoints.top() + 1;
-    mathfu::vec3* begin = end - hullPoints.size();
-    std::vector<mathfu::vec3> hullPointsArr(begin, end);
+//    mathfu::vec3* end   = &hullPoints.top() + 1;
+//    mathfu::vec3* begin = end - hullPoints.size();
+//    std::vector<mathfu::vec3> hullPointsArr(begin, end);
+    std::vector<mathfu::vec3> hullPointsArr;
+    hullPointsArr.reserve(hullPoints.size());
+    while(!hullPoints.empty()) {
+        hullPointsArr.push_back(hullPoints.top());
+        hullPoints.pop();
+    }
 
     mathfu::vec2 centerPoint = mathfu::vec2(0,0);
     for (int i = 0; i< hullPoints.size(); i++) {
diff --git a/wowViewerLib/src/engine/objects/scenes/map.cpp b/wowViewerLib/src/engine/objects/scenes/map.cpp
index c75cceba2..57aa85cc7 100644
--- a/wowViewerLib/src/engine/objects/scenes/map.cpp
+++ b/wowViewerLib/src/engine/objects/scenes/map.cpp
@@ -1983,7 +1983,7 @@ HDrawStage Map::doGaussBlur(const HDrawStage &parentDrawStage, HUpdateStage &upd
 
     //And the final is ffxglow to screen
     {
-        auto config = m_api->getConfig();;
+        auto config = m_api->getConfig();
 
         auto glow = parentDrawStage->frameDepedantData->currentGlow;
         auto ffxGlowfragmentChunk = m_api->hDevice->createUniformBufferChunk(sizeof(mathfu::vec4_packed));
diff --git a/wowViewerLib/src/engine/shader/ShaderDefinitions.h b/wowViewerLib/src/engine/shader/ShaderDefinitions.h
index 1cba25458..7add55634 100644
--- a/wowViewerLib/src/engine/shader/ShaderDefinitions.h
+++ b/wowViewerLib/src/engine/shader/ShaderDefinitions.h
@@ -975,8 +975,8 @@ const  std::unordered_map<std::string, std::unordered_map<int, std::vector<field
   {"ffxgauss4",  {
     {
       4, {
-        {"_33_texOffsetX", true, 0, 1, 4, 0},
-        {"_33_texOffsetY", true, 16, 1, 4, 0},
+        {"_36_texOffsetX", true, 0, 1, 4, 0},
+        {"_36_texOffsetY", true, 16, 1, 4, 0},
       }
     },
   }},
diff --git a/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.cpp b/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.cpp
index 39b8ec418..15a376007 100644
--- a/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.cpp
+++ b/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.cpp
@@ -997,10 +997,12 @@ void GDeviceVLK::updateBuffers(std::vector<std::vector<HGUniformBufferChunk>*> &
     }
 
     int fullSize = 0;
+    int fullTargetSize = 0;
     for (int i = 0; i < bufferChunks.size(); i++) {
         auto &bufferVec = bufferChunks[i];
         for (auto &buffer : *bufferVec) {
-            fullSize += buffer->getSize();
+            fullTargetSize = std::max<int>(fullTargetSize, fullSize + buffer->getSize());
+            fullSize += ((buffer->getRealSize() > 0) ? buffer->getRealSize() : buffer->getSize());
             int offsetDiff = fullSize % uniformBufferOffsetAlign;
             if (offsetDiff != 0) {
                 int bytesToAdd = uniformBufferOffsetAlign - offsetDiff;
@@ -1012,6 +1014,7 @@ void GDeviceVLK::updateBuffers(std::vector<std::vector<HGUniformBufferChunk>*> &
 
     //2. Create buffers and update them
     int currentSize = 0;
+    int targetSize = 0;
     int buffersIndex = 0;
 
     HGUniformBuffer bufferForUpload = m_UBOFrames[getUpdateFrameNumber()].m_uniformBufferForUpload;
@@ -1041,7 +1044,8 @@ void GDeviceVLK::updateBuffers(std::vector<std::vector<HGUniformBufferChunk>*> &
             for (auto &buffer : *bufferVec) {
                 buffer->setOffset(currentSize);
                 buffer->setPointer(&pointerForUpload[currentSize]);
-                currentSize += buffer->getSize();
+                targetSize = std::max<int>(targetSize, currentSize + buffer->getSize());
+                currentSize += ((buffer->getRealSize() > 0) ? buffer->getRealSize() : buffer->getSize());
 
                 int offsetDiff = currentSize % uniformBufferOffsetAlign;
                 if (offsetDiff != 0) {
@@ -1051,7 +1055,7 @@ void GDeviceVLK::updateBuffers(std::vector<std::vector<HGUniformBufferChunk>*> &
                 }
             }
         }
-        assert(currentSize == fullSize);
+        assert(targetSize == fullSize);
         for (int i = 0; i < bufferChunks.size(); i++) {
             auto &bufferVec = bufferChunks[i];
             auto frameDepData = frameDepedantData[i];
@@ -1070,9 +1074,11 @@ void GDeviceVLK::updateBuffers(std::vector<std::vector<HGUniformBufferChunk>*> &
 //                buffer->update(frameDepData);
 //            }
         }
-        if (currentSize > 0) {
+        if (targetSize > 0) {
             bufferForUploadVLK->uploadFromStaging(currentSize);
         }
+
+        m_uniformDataForUpload = currentSize;
     }
 }
 
diff --git a/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.h b/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.h
index ac56e3ab8..ab41ba5ec 100644
--- a/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.h
+++ b/wowViewerLib/src/gapi/vulkan/GDeviceVulkan.h
@@ -129,6 +129,10 @@ class GDeviceVLK : public IDevice, public std::enable_shared_from_this<GDeviceVL
     HGIndexBuffer createIndexBuffer() override;
     HGVertexBufferBindings createVertexBufferBindings() override;
 
+    int getUploadSize() override {
+        return m_uniformDataForUpload;
+    }
+
     HGTexture createBlpTexture(HBlpTexture &texture, bool xWrapTex, bool yWrapTex) override;
     HGTexture createTexture(bool xWrapTex, bool yWrapTex) override;
     HGTexture getWhiteTexturePixel() override { return m_whitePixelTexture; };
@@ -449,6 +453,7 @@ class GDeviceVLK : public IDevice, public std::enable_shared_from_this<GDeviceVL
     std::array<FrameUniformBuffers, 4> m_UBOFrames;
 
     std::vector<char> aggregationBufferForUpload = std::vector<char>(1024*1024);
+    int m_uniformDataForUpload = 0;
 
     std::list<DeallocationRecord> listOfDeallocators;
 

From 3e3decbae0498f7d570ef4b218d3d9dfb5c5ce35 Mon Sep 17 00:00:00 2001
From: Deamon87 <dmitolm@gmail.com>
Date: Thu, 13 Apr 2023 03:46:44 +0300
Subject: [PATCH 3/4] update Importer

---
 3rdparty/DBImporter   | 2 +-
 src/ui/FrontendUI.cpp | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/3rdparty/DBImporter b/3rdparty/DBImporter
index 51678fdff..efb859838 160000
--- a/3rdparty/DBImporter
+++ b/3rdparty/DBImporter
@@ -1 +1 @@
-Subproject commit 51678fdff7292747f089b5b207fb0b658927142b
+Subproject commit efb85983817d154203ff15d5b90cd4e48ef4af4e
diff --git a/src/ui/FrontendUI.cpp b/src/ui/FrontendUI.cpp
index 781153c6b..cc38929c6 100644
--- a/src/ui/FrontendUI.cpp
+++ b/src/ui/FrontendUI.cpp
@@ -718,9 +718,16 @@ void FrontendUI::showQuickLinksDialog() {
     if (ImGui::Button("Primal enchant", ImVec2(-1, 0))) {
         openM2SceneByfdid(4636728, replacementTextureFDids);
     }
+    if (ImGui::Button("nightborne model", ImVec2(-1, 0))) {
+        openM2SceneByfdid(1810676, replacementTextureFDids);
+    }
     if (ImGui::Button("Tomb of sargares hall", ImVec2(-1, 0))) {
         openMapByIdAndWDTId(1676, 1532459, 6289, -801, 3028);
     }
+    if (ImGui::Button("Legion Dalaran", ImVec2(-1, 0))) {
+        openWMOSceneByfdid(1120838);
+    }
+
     if (ImGui::Button("10.0 Raid WMO", ImVec2(-1, 0))) {
         openWMOSceneByfdid(4282557);
     }

From a4cff1cfa0a3bbd0da599e01b343fa93b569e80a Mon Sep 17 00:00:00 2001
From: Deamon87 <dmitolm@gmail.com>
Date: Thu, 13 Apr 2023 04:25:14 +0300
Subject: [PATCH 4/4] fix compilation on mac

---
 3rdparty/DBImporter                           |  2 +-
 .../src/engine/algorithms/grahamScan.cpp      | 43 ++++++++-----------
 2 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/3rdparty/DBImporter b/3rdparty/DBImporter
index efb859838..7188c49c3 160000
--- a/3rdparty/DBImporter
+++ b/3rdparty/DBImporter
@@ -1 +1 @@
-Subproject commit efb85983817d154203ff15d5b90cd4e48ef4af4e
+Subproject commit 7188c49c3a3ce1c309f71125876b60978b9ce213
diff --git a/wowViewerLib/src/engine/algorithms/grahamScan.cpp b/wowViewerLib/src/engine/algorithms/grahamScan.cpp
index 6955fb543..9c97d3673 100644
--- a/wowViewerLib/src/engine/algorithms/grahamScan.cpp
+++ b/wowViewerLib/src/engine/algorithms/grahamScan.cpp
@@ -3,14 +3,9 @@
 #include <algorithm>
 using namespace std;
 
-// Point having the least y coordinate, used for sorting other points
-// according to polar angle about this point
-//Point pivot;
-Point p0;
-
 // returns -1 if a -> b -> c forms a counter-clockwise turn,
 // +1 for a clockwise turn, 0 if they are collinear
-int ccw(Point a, Point b, Point c) {
+int ccw(const Point &a, const Point &b, const Point &c) {
     float area = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
     if (area > 0)
         return -1;
@@ -20,7 +15,7 @@ int ccw(Point a, Point b, Point c) {
 }
 
 // returns square of Euclidean distance between two points
-float sqrDist(Point a, Point b)  {
+float sqrDist(const Point &a, const Point &b)  {
     float dx = a.x - b.x, dy = a.y - b.y;
     return dx * dx + dy * dy;
 }
@@ -43,7 +38,7 @@ void swap(Point &p1, Point &p2)
 
 // A utility function to return square of distance
 // between p1 and p2
-int distSq(Point &p1, Point &p2)
+int distSq(const Point &p1, const Point &p2)
 {
     return (p1.x - p2.x)*(p1.x - p2.x) +
            (p1.y - p2.y)*(p1.y - p2.y);
@@ -54,7 +49,7 @@ int distSq(Point &p1, Point &p2)
 // 0 --> p, q and r are colinear
 // 1 --> Clockwise
 // 2 --> Counterclockwise
-int orientation(Point &p, Point &q, Point &r)
+int orientation(const Point &p, const Point &q, const Point &r)
 {
     int val = (q.y - p.y) * (r.x - q.x) -
               (q.x - p.x) * (r.y - q.y);
@@ -63,21 +58,6 @@ int orientation(Point &p, Point &q, Point &r)
     return (val > 0)? 1: 2; // clock or counterclock wise
 }
 
-// A function used by library function qsort() to sort an array of
-// points with respect to the first point
-int compare(const void *vp1, const void *vp2)
-{
-    Point *p1 = (Point *)vp1;
-    Point *p2 = (Point *)vp2;
-
-    // Find orientation
-    int o = orientation(p0, *p1, *p2);
-    if (o == 0)
-        return (distSq(p0, *p2) >= distSq(p0, *p1))? -1 : 1;
-
-    return (o == 2)? -1: 1;
-}
-
 Point nextToTop(stack<Point> &S)
 {
     Point p = S.top();
@@ -107,12 +87,23 @@ stack<Point> grahamScan(std::vector<Point> &points)    {
     // Place the bottom-most point at first position
     swap(points[0], points[min]);
 
+    // Point having the least y coordinate, used for sorting other points
+    // according to polar angle about this point
+    Point p0 = points[0];
+
     // Sort n-1 points with respect to the first point.
     // A point p1 comes before p2 in sorted ouput if p2
     // has larger polar angle (in counterclockwise
     // direction) than p1
-    p0 = points[0];
-    qsort(&points[1], n-1, sizeof(Point), compare);
+
+    std::sort(points.begin()+1, points.end(), [&p0](auto const &p1, auto const &p2) -> int {
+        // Find orientation
+        int o = orientation(p0, p1, p2);
+        if (o == 0)
+            return (distSq(p0, p2) >= distSq(p0, p1))? -1 : 1;
+
+        return (o == 2)? -1: 1;
+    });
 
     // If two or more points make same angle with p0,
     // Remove all but the one that is farthest from p0