44#include < array>
55#include < bitset>
66#include < iostream>
7+ #include < imgui.h>
78
8- #ifdef _DEBUG
9- #define ENABLE_NODE_ID_TESTER 1
10- #endif
11-
12- #ifdef ENABLE_NODE_ID_TESTER
13- // creates a list of which CullingNode IDs were added by the last distance increase loop
14- // and allow testing the distance increase with a given CullingNode skipped
15- // can help us to find which CullingNodes cause ugly LOD issues, and hopefully add them to filter list eventually
16- std::vector<uint16_t > lastAdds; // list of IDs added
17- uint16_t * lastAddsPtr = 0 ; // ptr to the lastAdds data, for ease of use with CE
18- int lastAddsNum = 0 ; // ObjectNum that we want to populate lastAdds for
19- int skipAddNum = -1 ; // if set, skips drawing this CullingNode ID, can be used to find which specific ID is troublesome
20- int skipObjNum = -1 ; // skips distance-increase for this ObjectNum, can be used to find which ObjectNum is troublesome
21- #endif
9+ std::array<std::vector<uint16_t >, 256 > ObjectNodes;
10+ std::array<std::bitset<16384 >, 256 > ObjectExclusions;
11+ int ExclusionsStageNum = 0 ; // stageid the exclusions are setup for, if stageid doesn't match current exclusions will be cleared
12+ int NumObjects = 0 ;
13+
14+ void Overlay_DrawDistOverlay ()
15+ {
16+ uint32_t cur_stage_num = Game::GetStageUniqueNum (Game::GetNowStageNum (8 ));
17+
18+ ImGui::Begin (" Draw Distance Debugger" );
19+
20+ ImGui::Checkbox (" Countdown timer enabled" , Game::Sumo_CountdownTimerEnable);
21+
22+ // get max column count
23+ int num_columns = 0 ;
24+ for (int i = 0 ; i < NumObjects; i++)
25+ {
26+ size_t size = ObjectNodes[i].size ();
27+ if (size > num_columns)
28+ num_columns = size;
29+ }
30+
31+ static ImGuiTableFlags table_flags = ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_HighlightHoveredColumn;
32+
33+ ImGui::Text (" How to use:" );
34+ ImGui::Text (" - When you see an ugly LOD object, pause the game with ESC, and press F11 to bring up this window" );
35+ ImGui::Text (" - Reduce the Draw Distance below to the lowest value which still shows the LOD object for you" );
36+ ImGui::Text (" - Once you find the draw-distance that shows the object, click each node checkbox until you find the node responsible" );
37+ ImGui::Text (" - After finding the node, you can hover over the checkbox to get the IDs for it" );
38+ ImGui::Text (" - Post the IDs for LODs you find in the \" DrawDistanceIncrease issue reports\" github thread and we can add exclusions for them!" );
39+ ImGui::NewLine ();
40+
41+ ImGui::SliderInt (" Draw Distance" , &Settings::DrawDistanceIncrease, 0 , 1024 );
42+ if (ImGui::Button (" <<<" ))
43+ Settings::DrawDistanceIncrease--;
44+ ImGui::SameLine ();
45+ if (ImGui::Button (" >>>" ))
46+ Settings::DrawDistanceIncrease++;
47+
48+ ImGui::Text (" cur_stage_num = 0x%X" , cur_stage_num);
49+
50+ if (num_columns > 0 )
51+ {
52+ ImGui::Text (" Nodes at DrawDistance %d:" , Settings::DrawDistanceIncrease);
53+
54+ num_columns += 1 ;
55+ if (ImGui::BeginTable (" table_angled_headers" , num_columns, table_flags))
56+ {
57+ ImGui::TableSetupColumn (" Object ID" , ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
58+ for (int n = 1 ; n < num_columns; n++)
59+ ImGui::TableSetupColumn (" " , ImGuiTableColumnFlags_WidthFixed);
60+
61+ for (int objectIdx = 0 ; objectIdx < NumObjects; objectIdx++)
62+ {
63+ ImGui::PushID (objectIdx);
64+ ImGui::TableNextRow ();
65+ ImGui::TableSetColumnIndex (0 );
66+ // ImGui::AlignTextToFramePadding();
67+ ImGui::Text (" Object %d" , objectIdx);
68+
69+ for (int i = 0 ; i < ObjectNodes[objectIdx].size (); i++)
70+ if (ImGui::TableSetColumnIndex (i + 1 ))
71+ {
72+ ImGui::PushID (i + 1 );
73+
74+ auto nodeId = ObjectNodes[objectIdx][i];
75+ bool excluded = ObjectExclusions[objectIdx][nodeId];
76+
77+ if (ImGui::Checkbox (" " , &excluded))
78+ ObjectExclusions[objectIdx][nodeId] = excluded;
79+
80+ ImGui::SetItemTooltip (" StageNum 0x%X, object 0x%X node 0x%X" , cur_stage_num, objectIdx, nodeId);
81+
82+ ImGui::PopID ();
83+ }
84+
85+ ImGui::PopID ();
86+ }
87+ ImGui::EndTable ();
88+ }
89+ }
90+
91+ if (ImGui::Button (" Clear all exclusions" ))
92+ {
93+ for (int i = 0 ; i < ObjectExclusions.size (); i++)
94+ ObjectExclusions[i].reset ();
95+ }
96+ if (ImGui::Button (" Copy exclusions to clipboard" ))
97+ {
98+ std::string clipboard = " " ;
99+ for (int objId = 0 ; objId < ObjectExclusions.size (); objId++)
100+ {
101+ for (int i = 0 ; i < ObjectExclusions[objId].size (); i++)
102+ {
103+ if (ObjectExclusions[objId][i])
104+ {
105+ clipboard += std::format (" StageNum 0x{:X}, object 0x{:X} node 0x{:X}\r\n " , cur_stage_num, objId, i);
106+ }
107+ }
108+ }
109+
110+ HGLOBAL hMem = GlobalAlloc (GMEM_MOVEABLE, clipboard.length ());
111+ if (hMem)
112+ {
113+ memcpy (GlobalLock (hMem), clipboard.c_str (), clipboard.length ());
114+ GlobalUnlock (hMem);
115+ OpenClipboard (0 );
116+ EmptyClipboard ();
117+ SetClipboardData (CF_TEXT, hMem);
118+ CloseClipboard ();
119+ }
120+ }
121+
122+ ImGui::End ();
123+ }
22124
23125class DrawDistanceIncrease : public Hook
24126{
@@ -75,7 +177,15 @@ class DrawDistanceIncrease : public Hook
75177 int v6 = ctx.ebx ;
76178 uint32_t * v11 = (uint32_t *)(v6 + 8 );
77179
78- int NumObjects = *(int *)(ctx.esp + 0x18 );
180+ uint32_t cur_stage_num = Game::GetStageUniqueNum (Game::GetNowStageNum (8 ));
181+ if (ExclusionsStageNum != cur_stage_num)
182+ {
183+ for (int i = 0 ; i < ObjectExclusions.size (); i++)
184+ ObjectExclusions[i].reset ();
185+ ExclusionsStageNum = cur_stage_num;
186+ }
187+
188+ NumObjects = *(int *)(ctx.esp + 0x18 );
79189 for (int ObjectNum = 0 ; ObjectNum < NumObjects; ObjectNum++)
80190 {
81191 CollisionNodesToDisplay.reset ();
@@ -94,44 +204,40 @@ class DrawDistanceIncrease : public Hook
94204 break ;
95205 }
96206
97- # ifdef ENABLE_NODE_ID_TESTER
98- if (ObjectNum == lastAddsNum && csOffset == Settings::DrawDistanceIncrease)
207+ // DEBUG: clear lastadds for this objectnum here
208+ if (csOffset == Settings::DrawDistanceIncrease)
99209 {
100- lastAdds .clear ();
210+ ObjectNodes[ObjectNum] .clear ();
101211 }
102- # endif
212+
103213 uint32_t sectionCollListOffset = *(uint32_t *)(v6 + *v11 + ((CsLengthNum + csOffset) * 4 ));
104214 uint16_t * sectionCollList = (uint16_t *)(v6 + *v11 + sectionCollListOffset);
215+
216+ int num = 0 ;
105217 while (*sectionCollList != 0xFFFF )
106218 {
107219 // If we haven't seen this CollisionNode idx already lets add it to our IdxArray
108220 if (!CollisionNodesToDisplay[*sectionCollList])
109221 {
110- #ifdef ENABLE_NODE_ID_TESTER
111- if (skipObjNum != ObjectNum || csOffset == 0 )
112- if (skipAddNum != *sectionCollList || skipAddNum < 0 || csOffset == 0 )
113- #endif
114- {
115- CollisionNodesToDisplay[*sectionCollList] = true ;
116- *cur = *sectionCollList;
117-
118- #ifdef ENABLE_NODE_ID_TESTER
119- if (ObjectNum == lastAddsNum && csOffset == Settings::DrawDistanceIncrease)
120- lastAdds.push_back (*cur);
121- #endif
122- cur++;
123- }
222+ CollisionNodesToDisplay[*sectionCollList] = true ;
223+
224+ // DEBUG: check exclusions here before adding to *cur
225+ // (if we're at csOffset = 0, exclusions are ignored, since that is what vanilla game would display)
226+ if (!ObjectExclusions[ObjectNum][*sectionCollList] || csOffset == 0 )
227+ {
228+ *cur = *sectionCollList;
229+ cur++;
230+ }
231+
232+ // DEBUG: add *sectionCollList to lastadds list here
233+ if (csOffset == Settings::DrawDistanceIncrease)
234+ ObjectNodes[ObjectNum].push_back (*sectionCollList);
235+
236+ num++;
124237 }
125238
126239 sectionCollList++;
127240 }
128-
129- #ifdef ENABLE_NODE_ID_TESTER
130- if (ObjectNum == lastAddsNum && csOffset == Settings::DrawDistanceIncrease)
131- {
132- lastAddsPtr = lastAdds.data ();
133- }
134- #endif
135241 }
136242
137243 *cur = 0xFFFF ;
@@ -155,15 +261,14 @@ class DrawDistanceIncrease : public Hook
155261
156262 bool apply () override
157263 {
158- #ifdef ENABLE_NODE_ID_TESTER
159- lastAdds.reserve (100 );
160- #endif
161-
162264 constexpr int DispStage_HookAddr = 0x4DF6D ;
163265
164266 Memory::VP::Nop (Module::exe_ptr (DispStage_HookAddr), 0x4B );
165267 dest_hook = safetyhook::create_mid (Module::exe_ptr (DispStage_HookAddr), destination);
166268
269+ for (int i = 0 ; i < ObjectNodes.size (); i++)
270+ ObjectNodes[i].reserve (4096 );
271+
167272 return true ;
168273 }
169274
0 commit comments