Repository navigation
Conversation
[Medium impact] The PR appears safe to merge; the previous missing-ground issue is fixed.
|
e001c0c to
c245104
Compare
|
Tidied the comments in
No functional change — comments only. |
Hi @Skyaero42, From the #2785 side, I think these are separate, complementary fixes rather than the same one:
Same file, but different functions ( They're actually complementary: #1711 raises the effective camera height on wide aspect ratios, which is exactly the zoomed-out condition where an un-sized terrain window stops covering the view and the water bleeds through. #2785 derives the window from the projected view corners, so it adapts automatically to whatever camera height #1711 produces. So #1711 can make the symptom more visible on wide screens, and #2785 fixes the rendering side of it. @Mauller can confirm the #1711 specifics/intent — I'm only speaking to how #2785 relates. Thanks! |
|
Hello @xezon @Skyaero42 I'd be happy to discuss or modify anything in this PR that you think is worth changing. I'm just trying to fix a display issue that I think is crucial given today's high resolutions. Thanks! |
|
I was able to test the fix during a 4h session (Generals Online fork with this fix backported), on various maps. All good ! |
|
There is a major deficit in reviewing capacity. You just gonna have to be patient. |
With the default settings (DrawEntireTerrain=No) the terrain is drawn only within a window of tiles around the view center. At high camera zoom this window no longer covers the visible ground, so any map water renders behind it. Maps that have no real water often still keep a map-sized "Default Water" polygon, which then makes the whole map look flooded. Players worked around this with DrawEntireTerrain=Yes, but that always draws the entire map and is very slow even at normal zoom (TheSuperHackers#2743). This change instead sizes the normal draw window to the actual visible footprint: it projects the four view corners onto the ground plane (the same method updateCenter() uses to position the window) and grows the draw size just enough to span them, bounded by the map extent and snapped to whole vertex-buffer tiles. At normal zoom the footprint is smaller than the normal window, so this is a no-op and behavior is unchanged; the window only grows as the camera zooms out. This does not change the DrawEntireTerrain path, but removes the need for it in the common case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
c245104 to
bf9ab08
Compare
The terrain draw-window growth added in the previous commit was gated to the user-controlled camera only. The scripted camera, for example the main menu shell map, can also view past the regular draw window, which left the ground uncovered and the water plane showing through. Apply the growth to the scripted camera as well. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
@Skyaero42 @xezon Update now that #2846 has landed. I rebased this PR on top of it, and the fix now lives inside the new Why it's still worth having alongside #2846:
So the two are complementary: #2846 makes the "draw everything" workaround fast; this PR removes the need for that workaround in the common case by sizing the draw window to the actual visible footprint. It's a no-op at normal zoom and grows only as you zoom out, bounded by the map extent and snapped to tile blocks so it doesn't reallocate every frame. The latest commit also extends the coverage to the scripted camera (for example the main-menu shell map), which can likewise see past the regular window. Happy to tweak anything. |
|
I did some quick performance comparisons:
@sailro Can you verify these findings? I'd be hesitant to add this code for |
The previous snapping always added a full spare vertex-buffer block (32 tiles) of margin before rounding up, so the draw window grew one block earlier than geometrically necessary. A footprint of 96-128 tiles - which the normal 129-vertex window (128 tiles) still covers - was drawn with a 161 window (25 blocks instead of 16, +56% terrain blocks), and some viewport aspect ratios crossed that threshold even at normal zoom. Compute the required block count directly with a ceiling division and add only a small centering margin (CENTER_LIMIT-sized), so the window stays at the normal size until the footprint truly exceeds it. This keeps the zoomed-out coverage while making the change a genuine no-op at normal zoom. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
@Caball009 Thanks a lot for profiling this - your finding was real and pointed at an actual inefficiency in my code, which I've now fixed (latest commit). Root cause of the drop you saw with The fix:
So at any camera height where the visible terrain fits the normal window, this is now a genuine no-op - only the four corner-ray projections run, and On the two cost sources when actually zoomed out:
Comparing against the On your suggestion to apply it for Happy to share raw numbers or a capture if useful. |
|
@Caball009 happy to discuss or modify anything in this PR that you think is worth changing. Thanks ! |
Ray direction normalization is unnecessary for a line-plane intersection, and the previous code solved the X and Y coordinates with separate divisions. Use the unnormalized direction and a shared scale instead, removing four inverse square roots and four divisions from each draw-size recalculation. Use the project clamp helper for finite and infinite intersections while preserving the conservative NaN fallback for parallel rays. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
@Skyaero42 thank you for this review. So I think I addressed both comments in my last fixing commit.
This removes four inverse-square-root operations and four divisions per draw-size recalculation. The calculation only runs when the camera transform changes, not while stationary. |
|
@Skyaero42 @Caball009 I've been testing this for weeks with private builds / private online lobbies with friends on Generals Online. Works well from my point of view. Happy to discuss or modify anything in this PR that you think is worth changing. Thanks ! |
|
Yeah, I still need to do another round of reviewing. I'll try to get to it. |
|
@sailro Try rotating the map at very high camera heights. It's fine with |
|
The original height map update is inefficient, not necessarily caused by this Pull |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57b230fec5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Size terrain from a yaw-invariant footprint diameter across the terrain height range, and reuse its center instead of rescanning the heightmap. Bound horizon-crossing projections by the map and round coverage upward with enough margin for origin drift and grid rounding. Pass the optional center through the renderer interfaces while retaining the legacy centering path for callers that do not provide it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
Thanks @Caball009, @xezon, @OmarAglan and @Skyaero42. I reproduced the rotation regression and pushed a follow-up commit. My earlier square-window claim was wrong: its world-axis spans still changed with yaw, triggering buffer rebuilds. Idle-machine comparison: previous PR state vs this fix; Win32 Release, 1280x720 windowed, uncapped, verified camera heights, two 20-second runs per case with continuous rotation.
The patched draw size stayed constant; the old revision had 260/460 observed size changes at 850/1500 across 40 seconds each. Why eight files now: sizing and centering must agree. |
Reuse vector bounds helpers and the validated camera transform. Defer minimum-size calculations until projection succeeds, and derive padding from the renderer's shared centering tolerance without changing behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
Restore the existing CENTER_LIMIT define alongside the other renderer limits instead of exposing it in the public header. Keep the documented five-cell padding and the other footprint cleanup unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
I don't know how much of a problem this will be realistically, but there's a very noticeable lag that happens when zooming in / out at extremely high camera heights >= 1200. Try with 2500 for instance. You can use numpad 4 & 8 for smoother zooming than using the scroll button. |
Yes it is probably quite an edge case at those zoom-levels but the culprit is the full terrain rebuild whenever zoom crosses a 32-tile size threshold.
The minimal approach would retain the larger terrain window during zooming and add modest growth headroom, rather than shrinking and rebuilding at every threshold. That reduces repeated stalls, but temporarily draws more terrain and won’t eliminate first-time growth stalls. But the complete fix would reuse existing buffers and update only newly needed regions. That touches more renderer internals and needs broader testing. Perhaps for another follow-up PR ? I think what we have now is quite nice: solve the issue and is now quite performant thanks to the reviews. |
TheSuperHackers#2785) Applied from TheSuperHackers#2785 by sailro (open, unmerged), squashed from fork branch fix/terrain-cover-visible-ground-at-zoom head 6fffd07 against its base e378776. Sizes the terrain draw window to the camera's projected ground footprint, so zoomed-out views no longer show units and structures floating past the terrain edge. Replace with the merged upstream version when GeneralsOnline picks it up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Using this latest version for weeks without any issue. |
|
It's still on my todo list to look at again. I don't know enough about the code specifically to review it properly, though, but I can test gameplay and performance. |
| return false; | ||
|
|
||
| // A horizon-crossing or invalid projection has no finite footprint. Keep the map-sized fallback. | ||
| dimensions.x = map->getXExtent(); |
There was a problem hiding this comment.
When the top of the view shows sky the corner rays miss the ground, and this falls back to the full map. Cutscenes and low pitch cameras then draw the whole map. Can it use the normal or low angle size instead?
There was a problem hiding this comment.
Fixed in 1f6460baf. Horizon-crossing corner rays now use the normal or low-angle minimum draw size and leave centering to the existing calcVis/low-pitch path instead of resizing to the full map.
There was a problem hiding this comment.
Follow-up after runtime testing: using the normal/low-angle minimum here is not safe, so I reverted that part in 95f3f4d92. On Whiteout at height 1500 and 10° pitch, the minimum fallback selected 257x257 and left large black terrain gaps with floating objects; the conservative map fallback selected 540x540 and rendered correctly. The separate change to use the projected center only after the window expands remains in place.
Use the normal or low-angle window when the view crosses the horizon instead of falling back to the full map. Reuse the projected footprint center only when dynamic sizing grows beyond that minimum, leaving ordinary views on the existing centering paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Camera-footprint sizing Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h, Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp |
getDesiredTerrainDrawSize calculates dimensions from projected view bounds, map limits, and pitch-dependent minimums. It supplies a draw center when the dimensions exceed the minimum. |
Centered terrain updates Core/GameEngineDevice/Include/W3DDevice/GameClient/*HeightMap.h, Core/GameEngineDevice/Source/W3DDevice/GameClient/*HeightMap.cpp, Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp |
Height-map update methods accept and forward an optional draw center. When supplied, HeightMapRenderObjClass uses it to calculate the terrain origin and skips the alternating X-update delay. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Bug fix · Severity of issue fixed: Medium
Sequence Diagram(s)
sequenceDiagram
participant W3DView
participant HeightMapRenderObjClass
participant BaseHeightMapRenderObjClass
W3DView->>HeightMapRenderObjClass: pass optional drawCenter to updateCenter
HeightMapRenderObjClass->>BaseHeightMapRenderObjClass: forward drawCenter
HeightMapRenderObjClass->>HeightMapRenderObjClass: compute origin from drawCenter when provided
Suggested reviewers: xezon
Merge Risk: 
Minimal · up to 95f3f
-
No unresolved terrain-coverage issue is established by this review; the change is mergeable after normal checks.
Pre-merge checks: 
4
-
Full details: Out of Scope Changes check
-
Explanation
The reported changes stay within terrain draw-window sizing and centering. W3DView computes the visible footprint and passes the selected draw center through the HeightMap update path. Header and implementation signature changes support that behavior. No unrelated change is identified.
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Restore the map-sized fallback when a view ray reaches the horizon. A Whiteout runtime comparison at height 1500 and 10 degrees showed that reducing this case to the 257x257 low-angle minimum leaves large terrain gaps, while the 540x540 map fallback remains complete. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6fc47f85-1023-4457-9df0-8e97163e72f0
Problem
With the default settings (
DrawEntireTerrain=No) the terrain is only drawn within a window of tiles around the view center. At high camera zoom this window no longer covers the visible ground, so any map water renders behind it. Many maps that have no real water still keep a map-sized "Default Water" polygon, which then makes the whole map look flooded when the camera is zoomed out.The legacy workaround was
DrawEntireTerrain=Yes, but that always draws the entire map and is very slow even at normal zoom (#2743).Fix
Size the normal draw window to the actual visible footprint instead of a fixed tile count:
updateCenter()already uses to position the window).NaNdraw size.At normal zoom the footprint is smaller than the normal window, so this is a no-op and behavior is unchanged; the window only grows as the camera zooms out. It works for all maps.
This change lives in the default
DrawEntireTerrain=Nopath. It does not modify theDrawEntireTerrainpath, so it does not by itself resolve #2743 — it removes the need for that slow workaround in the common case.Before / After
Before — zoomed out on a no-water map, the terrain window ends and the map's default water polygon fills the rest of the view:
After — the draw window covers the visible ground, so the sand renders all the way out (same scene type, patched build):
After on a stock map (Whiteout) — the real lake still renders correctly and the terrain fills the view (the black wedge top-left is genuinely off-map, past the terrain border at extreme zoom):
Testing
DrawEntireTerrain=Yes-style degradation).AI disclosure
Per the contribution guidelines: the code in this PR was written with the help of an LLM (GitHub Copilot CLI) and then reviewed, iterated on, and verified by a human. The approach — projecting the view footprint the same way
updateCenter()does, tile snapping, and map-extent /NaNbounding — was chosen deliberately, and the change was validated in-game across several maps and zoom levels. The diff is intentionally small and self-contained: one file, only the draw-size calculation inupdateTerrain().cc @xezon