render parity unit J: 40250 automatic sight range in CPythonApplication::Process
Process now runs 40250's render-time / face-count block and sets view distance set 0 each frame (25600 under 5000 faces, else scaled by render time, or the forced range). SetForceSightRange and SkipRenderBuffering are ported from stubs; the invented SetCursorPosition in UpdateGame is removed. Port-map boilerplate notes replaced; Destroy recorded as DIVERGENT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0e8a1574cb
commit
dda885a17a
@@ -567,3 +567,4 @@
|
||||
{"date": "2026-09-28T04:56:02+00:00", "unit": "GameLib/MapOutdoorRenderHTP.cpp", "action": "unit H1: platform rewrite replaced by the full 40250 source (native-terrain gate only); drops the invented texture-0 fallback splat, restores first-splat stage-1 ALPHAOP DISABLE, GetNumTextures() loop bound, shadow-pass FOGCOLOR white/restore, stage-0 ALPHAOP DISABLE + CLAMP, TEXTURE1 = m_matDynamicShadow, stage-1 SELECTARG1 restore, TEXTURE0 1/640 tiling", "evidence": "ctest (see commit); fake-server frame 900: white far band gone, terrain matches STP-path layout (mean abs diff vs STP ~20/255 from per-texture m_matTransform vs STP's fixed 1/640, as in 40250); HTP pixels NEEDS_LIVE"}
|
||||
{"date": "2026-09-28T04:59:25+00:00", "unit": "GameLib/MapOutdoorWater.cpp", "action": "unit H2: platform rewrite replaced by the full 40250 source (native-terrain gate only): far-fog second water pass restored, invented LIGHTING=FALSE save/restore and empty-texture guard removed", "evidence": "build ok; fake-server spawn frame 900 unchanged (mean abs diff ~0.4/255, no water in view); water visuals NEEDS_LIVE"}
|
||||
{"date": "2026-09-28T05:08:46+00:00", "unit": "EterPythonLib/PythonGraphic.cpp", "action": "unit I: SetGamma, RenderCoolTimeBox, RenderUp/DownButton, GetAvailableMemory ported from 40250 (stubs removed); cooldown fan drawn as polygon UI commands; SetViewport/RestoreViewport documented as ADAPTED (device viewport + UI clip)", "evidence": "port.app_loop drawing_primitives checks fan geometry at fTime 0.25/0.3/1.0 and viewport clip push/pop; cooldown visuals NEEDS_LIVE"}
|
||||
{"date": "2026-09-28T05:22:26+00:00", "unit": "UserInterface/PythonApplication.cpp", "action": "unit J: Process gains 40250's render-time/face-count block and automatic sight range (SetViewDistanceSet(0)); SetForceSightRange/SkipRenderBuffering ported from stubs; invented SetCursorPosition in UpdateGame removed; boilerplate notes on RenderGame/UpdateGame/Process/Destroy replaced (Destroy marked DIVERGENT: never called, teardown via PythonBoot::Stop)", "evidence": "ctest -j3 35/35; fake-server spawn frame 900 mean abs diff 0.33/255 vs previous (fog range not in view); sight-range visuals NEEDS_LIVE"}
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::SetMinFog"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"test": "extension/tests/port_login_flow_test.cpp",
|
||||
"note": "40250 body verbatim in the platform layer."
|
||||
},
|
||||
"CPythonApplication::SetFrameSkip": {
|
||||
"status": "ADAPTED",
|
||||
@@ -73,32 +73,32 @@
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::RenderGame"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"test": "extension/tests/port_login_flow_test.cpp",
|
||||
"note": "40250's !PERF_CHECKER_RENDER_GAME branch line for line, members reached through their singletons; the perf-timing branch (PERF_CHECKER_RENDER_GAME is FALSE) is left out."
|
||||
},
|
||||
"CPythonApplication::UpdateGame": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::UpdateGame"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"test": "extension/tests/port_login_flow_test.cpp",
|
||||
"note": "40250 body through the singletons, minus the __PERFORMANCE_CHECK__/PERF_CHECKER timing. An invented CScreen::SetCursorPosition in the perspective block was removed (unit J): as in 40250 the pick ray comes from RenderGame's SetCursorPosition."
|
||||
},
|
||||
"CPythonApplication::SkipRenderBuffering": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::SkipRenderBuffering"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"test": "extension/tests/port_login_flow_test.cpp",
|
||||
"note": "40250 body verbatim in the platform layer."
|
||||
},
|
||||
"CPythonApplication::Process": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::Process"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"test": "extension/tests/port_login_flow_test.cpp",
|
||||
"note": "Frame order as 40250 (network, account connector, camera, resource, mouse/UI update, specular, culling, Begin/UI/mouse render/End). Left out: guild mark up/download (not ported), lost-device restore, ClearDepthBuffer/Show (host presents), frame-skip timing/Sleep (host paces frames), FPS counters, and the !IsActive() SkipRenderBuffering(3000) (CMSWindow::IsActive is a stub). Unit J restored 40250:741-842: render time, face count, frame buffering average and the automatic sight range (SetViewDistanceSet(0, ...): 25600 under 5000 faces, else MIN_FOG..25600 scaled by render time, or the forced range), with a PORT guard on the face-speed division. Fog/far-clip effect NEEDS_LIVE against the reference frame."
|
||||
},
|
||||
"CPythonApplication::UpdateClientRect": {
|
||||
"status": "ADAPTED",
|
||||
@@ -285,7 +285,7 @@
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::SetForceSightRange"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"note": "40250 body verbatim in the platform layer. m_iForceSightRange lives in the file-static s_iForceSightRange (initial -1 as the 40250 constructor sets) until the application object exists.",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
},
|
||||
"CPythonApplication::Clear": {
|
||||
@@ -297,12 +297,11 @@
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
},
|
||||
"CPythonApplication::Destroy": {
|
||||
"status": "ADAPTED",
|
||||
"status": "DIVERGENT",
|
||||
"impl": [
|
||||
"extension/src/platform/UserInterface/PythonApplication.cpp:CPythonApplication::Destroy"
|
||||
],
|
||||
"note": "40250 CPythonApplication lifecycle and state adapted for platform host and singletons",
|
||||
"test": "extension/tests/port_login_flow_test.cpp"
|
||||
"note": "Empty and never called: the host tears down through the singleton resets in PythonBoot::Stop, not 40250 Main's app->Destroy(). 40250's body (window manager, SaveConfig/SaveInterfaceStatus writing into the client dir, managers incl. m_LightManager.Destroy(), device) is not run; porting it needs Stop to call it with config writes redirected out of the 40250 client dir."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ float CPythonApplication::GetGlobalTime() { return CTimer::Instance().GetCurrent
|
||||
// PORT: read straight from the timer, as GetGlobalTime above.
|
||||
float CPythonApplication::GetGlobalElapsedTime() { return CTimer::Instance().GetElapsedSecond(); }
|
||||
static bool s_isFrameSkipDisable = false;
|
||||
// m_iForceSightRange (the 40250 constructor sets -1: automatic sight range).
|
||||
static int s_iForceSightRange = -1;
|
||||
void CPythonApplication::SetFrameSkip(bool isEnable) { s_isFrameSkipDisable = !isEnable; }
|
||||
// PORT: 40250 creates the Win32 window, the D3D8 device, cursors, sound, keyboard, the net device,
|
||||
// fonts and the IME here. The Godot window and its canvas already exist when the host starts the
|
||||
@@ -261,7 +263,6 @@ void CPythonApplication::UpdateGame()
|
||||
|
||||
s.SetPerspective(30.0f,fAspect, 100.0f, fFarClip);
|
||||
s.BuildViewFrustum();
|
||||
s.SetCursorPosition(ptMouse.x, ptMouse.y, UI::CWindowManager::Instance().GetScreenWidth(), UI::CWindowManager::Instance().GetScreenHeight());
|
||||
}
|
||||
|
||||
TPixelPosition kPPosMainActor;
|
||||
@@ -315,8 +316,11 @@ bool CPythonApplication::Process()
|
||||
if (IsNativeTerrainRenderEnabled())
|
||||
CGrannyMaterial::TranslateSpecularMatrix(g_specularSpd, g_specularSpd, 0.0f);
|
||||
|
||||
// PORT: the render block without the lost-device restore, ClearDepthBuffer, Show and the render-time
|
||||
// statistics (Godot clears and presents the frame). The frame's UI and 3D command lists restart here.
|
||||
// PORT: the render block without the lost-device restore, ClearDepthBuffer and Show (Godot clears
|
||||
// and presents the frame), and without the !IsActive() SkipRenderBuffering(3000): the host has no
|
||||
// Win32 activation (CMSWindow::IsActive is a stub). The frame's UI and 3D command lists restart here.
|
||||
// 40250 PythonApplication.cpp:681.
|
||||
DWORD dwRenderStartTime = ELTimer_GetMSec();
|
||||
CCullingManager::Instance().Update();
|
||||
UIRenderBeginFrame();
|
||||
Render3DBeginFrame();
|
||||
@@ -336,6 +340,93 @@ bool CPythonApplication::Process()
|
||||
}
|
||||
|
||||
rkGraphic.End();
|
||||
|
||||
// 40250 PythonApplication.cpp:741-842 (render time, face count, automatic sight range), minus the
|
||||
// per-second FPS/face counters and the windowed dwBufRenderTime rounding, whose result 40250 never
|
||||
// uses (its Sleep is commented out).
|
||||
DWORD dwRenderEndTime = ELTimer_GetMSec();
|
||||
|
||||
static DWORD s_dwRenderCheckTime = dwRenderEndTime;
|
||||
static DWORD s_dwRenderRangeTime = 0;
|
||||
static DWORD s_dwRenderRangeFrame = 0;
|
||||
|
||||
m_dwCurRenderTime = dwRenderEndTime - dwRenderStartTime;
|
||||
s_dwRenderRangeTime += m_dwCurRenderTime;
|
||||
++s_dwRenderRangeFrame;
|
||||
|
||||
if (dwRenderEndTime-s_dwRenderCheckTime>1000)
|
||||
{
|
||||
m_fAveRenderTime=float(double(s_dwRenderRangeTime)/double(s_dwRenderRangeFrame));
|
||||
|
||||
s_dwRenderCheckTime=ELTimer_GetMSec();
|
||||
s_dwRenderRangeTime=0;
|
||||
s_dwRenderRangeFrame=0;
|
||||
}
|
||||
|
||||
DWORD dwCurFaceCount=rkGraphic.GetFaceCount();
|
||||
rkGraphic.ResetFaceCount();
|
||||
|
||||
if (dwCurFaceCount > 5000)
|
||||
{
|
||||
// 프레임 완충 처리
|
||||
if (dwRenderEndTime > m_dwBufSleepSkipTime)
|
||||
{
|
||||
static float s_fBufRenderTime = 0.0f;
|
||||
|
||||
float fCurRenderTime = m_dwCurRenderTime;
|
||||
|
||||
if (fCurRenderTime > s_fBufRenderTime)
|
||||
{
|
||||
float fRatio = fMAX(0.5f, (fCurRenderTime - s_fBufRenderTime) / 30.0f);
|
||||
s_fBufRenderTime = (s_fBufRenderTime * (100.0f - fRatio) + (fCurRenderTime + 5) * fRatio) / 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float fRatio = 0.5f;
|
||||
s_fBufRenderTime = (s_fBufRenderTime * (100.0f - fRatio) + fCurRenderTime * fRatio) / 100.0f;
|
||||
}
|
||||
|
||||
// 한계치를 정한다
|
||||
if (s_fBufRenderTime > 100.0f)
|
||||
s_fBufRenderTime = 100.0f;
|
||||
|
||||
m_fAveRenderTime=s_fBufRenderTime;
|
||||
}
|
||||
|
||||
m_dwFaceAccCount += dwCurFaceCount;
|
||||
m_dwFaceAccTime += m_dwCurRenderTime;
|
||||
|
||||
// PORT: recording a frame can take under 1 ms, so the integer division is guarded (40250's
|
||||
// D3D frame never took 0 ms).
|
||||
if (m_dwFaceAccTime)
|
||||
m_fFaceSpd=(m_dwFaceAccCount/m_dwFaceAccTime);
|
||||
|
||||
// 거리 자동 조절
|
||||
if (-1 == s_iForceSightRange)
|
||||
{
|
||||
static float s_fAveRenderTime = 16.0f;
|
||||
float fRatio=0.3f;
|
||||
s_fAveRenderTime=(s_fAveRenderTime*(100.0f-fRatio)+max(16.0f, m_dwCurRenderTime)*fRatio)/100.0f;
|
||||
|
||||
|
||||
float fFar=25600.0f;
|
||||
float fNear=MIN_FOG;
|
||||
double dbAvePow=double(1000.0f/s_fAveRenderTime);
|
||||
double dbMaxPow=60.0;
|
||||
float fDistance=max(fNear+(fFar-fNear)*(dbAvePow)/dbMaxPow, fNear);
|
||||
CPythonBackground::Instance().SetViewDistanceSet(0, fDistance);
|
||||
}
|
||||
// 거리 강제 설정시
|
||||
else
|
||||
{
|
||||
CPythonBackground::Instance().SetViewDistanceSet(0, float(s_iForceSightRange));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 10000 폴리곤 보다 적을때는 가장 멀리 보이게 한다
|
||||
CPythonBackground::Instance().SetViewDistanceSet(0, 25600.0f);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -483,7 +574,11 @@ time_t CPythonApplication::GetServerTime() { return GetPlatformServerTime(); }
|
||||
time_t CPythonApplication::GetServerTimeStamp() { return GetPlatformServerTimeStamp(); }
|
||||
void CPythonApplication::SetConnectData(const char*, int) { MT_PLATFORM_STUB(); }
|
||||
void CPythonApplication::GetConnectData(std::string& ip, int& port) { MT_PLATFORM_STUB(); ip.clear(); port = 0; }
|
||||
void CPythonApplication::SetForceSightRange(int) { MT_PLATFORM_STUB(); }
|
||||
// 40250 PythonApplication.cpp:1377.
|
||||
void CPythonApplication::SetForceSightRange(int iRange)
|
||||
{
|
||||
s_iForceSightRange = iRange;
|
||||
}
|
||||
|
||||
int CPythonApplication::CheckDeviceState()
|
||||
{
|
||||
@@ -506,9 +601,10 @@ void CPythonApplication::NotifyHack(const char* c_szFormat, ...)
|
||||
CPythonNetworkStream::Instance().NotifyHack(szBuf);
|
||||
}
|
||||
|
||||
// 40250 PythonApplication.cpp:394
|
||||
void CPythonApplication::SkipRenderBuffering(DWORD dwSleepMSec)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_dwBufSleepSkipTime=ELTimer_GetMSec()+dwSleepMSec;
|
||||
}
|
||||
|
||||
void CPythonApplication::UpdateClientRect()
|
||||
|
||||
Reference in New Issue
Block a user