Fun experiment: an explorable toroidal world - #139
Conversation
# Conflicts: # SConstruct # libgag/src/GraphicContext.cpp
Vertical torus navigation now moves only the map surface. Draw units at the wrapped cell supplied by map traversal instead of recomputing their position with a small-viewport margin, which hid explorers near full-world capture edges. Cover moving explorer copies across both seams in GPU and software integration checks.
|
@Giszmo Thanks for the feedback and the work on
After further playtesting, I’ve kept 2D and 3D as separate modes, switched explicitly with G. The movement-triggered pullback and snapback interrupted ordinary scrolling. Normal 2D now stays on its regular viewport renderer without full-world captures or torus mesh updates; the torus remains optional. The separated modes felt much better in playtesting. I’ve also cleaned up the implementation: camera/input state is separate from OpenGL drawing and resource ownership, the automatic folding state is removed, and both views reuse the game’s map renderer. Software rendering remains supported, including builds without OpenGL. Local OpenGL and software rendering checks pass, along with the software-only build/startup checks. CI is running on the latest changes. The PR description and rendering notes now reflect this version. This still uses the master baseline rather than merging the separate refactoring/fullscreen branches. I haven’t reproduced your native startup/display failure; could you share the error or steps that trigger it, and whether the latest version still fails on your setup? I’d appreciate another look at this version when you have time. |
The map-to-screen helper folds the last 16 tile columns and rows of a view to negative coordinates, which suits a screen much smaller than the map but throws a 512 px band of a whole-map capture off its edge: units and buildings standing there were never painted into the torus texture, and which colony that hit depended on where the capture origin fell. Units now draw at the cell the traversal visited, and buildings at each wrapped copy whose sprite reaches into the view, so a seam shows both halves. Diagnosis by genixpro in #139. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@genixpro The startup/display failure is not torus-specific, it is master on a 3840x2160 Wayland desktop. The fixes master lacks, in dependency order:
So: rebase (written by Bob, my agent) |
Profile the 256x256 Oazis map, remove unused cloud generation, limit overview sampling and atlas memory, and eliminate per-sprite GPU state changes in batched drawing. Preserve native 2D detail and the software path. Add a repeatable loaded-game benchmark and pixel comparisons for variable-size atlas rendering.
|
@Giszmo can we split the difference and make the torus zoom-out and snap-back mode configurable? I've found it very awkward in my testing |
Keep explicit mode switching as the default. Add a persistent in-game option for gradual movement-triggered folding and quick return, with G pinning and pointer gesture protection. Preserve software rendering and keep the PR based on master.
|
@Giszmo The two navigation styles are now supported through Settings → General Settings → Automatic torus view from the main menu. It is off by default, preserving explicit G switching. Enabling it gives gradual folding while scrolling and a quick return after movement stops; G keeps the overview open. The preference is saved locally, and automatic transitions wait for selection/painting gestures to finish. Software rendering stays in 2D. Further profiling on a 256 × 256 map also exposed redundant cloud generation and sprite submission overhead. The rendering benchmark improved from about 130 ms to 12–16 ms per frame on the M3, with the map still refreshing every frame. GPU and software checks pass, including pixel comparisons for the resource batching change. Thanks for explaining the Wayland failure. I understand that it belongs to master’s fullscreen scaling rather than this feature. I’d like to keep this PR independent and focused while #129 and #132 are still pending, rather than coupling it to that larger dependency chain. This leaves the Wayland issue outstanding here until the separate scaling work lands. |
|
You could also help make those other improvements land ;) |
Giszmo
left a comment
There was a problem hiding this comment.
NACK while we fix bugs. Don't make the revival harder than it is with fun experiments. I fell for the temptation to play with that torus view and would advocate to switch it on by default but merging 3k LOC in a major refactoring effort is counter productive.
|
@Giszmo I've moved this PR to draft for now and merged current master, including the refactoring and fullscreen-scaling work now that those PRs have landed. The torus integration follows the new GUI/render modules and separate viewer and pending-building state. Explicit G switching remains the default, with automatic folding off by default in the main Settings menu. The integration also caught a nearest-neighbour sampling mismatch between standalone and atlas resource sprites; that is fixed, with identical pixels at native, reduced and enlarged scales. Local OpenGL and software-only build/rendering checks pass, as do the broader test executables and the selection/terrain regressions. The 256 × 256 rendering benchmark remains about 12 ms per frame with clouds on the M3 (rendering only). I'll keep the draft current with master and resolve integration conflicts as they arise. Native Wayland playtesting of the combined changes is still needed. |
|
@Giszmo Thanks for the rectangular-map examples. Addressed in 1016f0b: the torus ring/tube proportions now follow the map dimensions, with isothermal texture coordinates so tiles stay locally square on the surface. Wide maps produce thinner rings and tall maps produce fatter ones. Tile area still changes around the tube, and perspective still foreshortens it. The geometry is shared by rendering, clouds and picking; the fitting/mesh caches also account for map aspect ratio. Mesh size stays fixed. I checked 64 × 128, 512 × 64, 64 × 512 and square terrain grids, including transitions, wrapped picking and changing map dimensions. OpenGL and software-only builds/rendering pass, as do geometry/picking tests under ASan/UBSan. The 256 × 256 Oazis rendering benchmark measured 16.64 ms median with clouds in this run on the M3 (rendering only). Keeping this in draft and current with master while the revival work settles. Manual mode switching remains the default, automatic folding remains opt-in in the main Settings menu, and native Wayland playtesting is still outstanding. |
|
Visual evidence for the map-proportion fix in 1016f0b. These are actual OpenGL renders using the benchmark’s synthetic checkerboard terrain, which makes tile proportions easier to compare. Dimensions below are map width × height.
Tall maps produce a fatter tube and wide maps a thinner ring. The visual priority is square-looking tiles in the visible, camera-facing region. The mapping preserves local surface proportions; perspective still compresses tiles as the surface turns away, and tile area varies around the tube. Distortion at the sides and inner opening is less important than readability in the main visible region. Click an image for full resolution. To reproduce, build |
Integrate master through 95de302, preserving torus rendering, software fallback and sprite batching across the identifier cleanup and fullscreen letterboxing. Keep the optional torus setting alongside the new game-speed controls. Use a numerically resolvable finite-difference interval in the tile-proportion test on non-FMA platforms without relaxing its tolerance.
|
Maintenance update: merged master through 95de302 in 3cc46b1 and resolved the conflicts with the identifier cleanup, fullscreen letterboxing, and new game-speed settings. Both settings are available without overlapping; manual G switching remains the default and automatic torus folding stays off by default. The Linux/Windows failure on 1016f0b was a numerically unstable finite-difference test on the very small inner wall of a tall-map torus. I reproduced it locally with fused multiply-add disabled and increased the sampling interval without relaxing the accuracy threshold or changing the renderer. Geometry and picking now pass locally with FMA disabled and with ASan/UBSan. OpenGL and software-only builds/rendering, software-only startup with GPU mode requested, rectangular-map fitting/picking, fullscreen aspect-ratio checks, game-speed controls/playback, and the selection, terrain, wrapped-building, entering-unit and savegame regressions pass locally. Resource-atlas comparisons still have zero differing pixels. The latest 256 × 256 rendering-only benchmark measured 11.4 ms median with clouds on the M3. CI is running for the new merge; the PR remains draft, and native Wayland playtesting is still outstanding. |
|
Note/question: did you consider rendering the units in 3D? The repository has the 3D models of the globules in Blender. Also, we could try to see if there exist tools to create 3D models from 2D images, for the other elements. That could create a small world/little planet style. Of course, this would make the two rendering paths (2D and torus) very different and thus increase the load time if done naively, but probably some on-demand loading could be done. |
That would be a separate PR but of course, wrapping a 3D world into a torus might have extra challenges compared to the mere 2D wrapping.
That checkered torus images are a great way to visualize the problem. I would tilt the torus though to fill the screen's aspect ratio or even allow it to crop left and right to focus more on the front facing landscape. |
Without thinking too much about it, I do not expect to be too hard to transform an (x, y, z) coordinate (for z << x or y) onto the torus coordinates. I imagine we can do that on the shader itself. Because you basically take (x, y), map it on the torus 3D point, then multiply z with the unitary normal at that point, and voilà. |
|
@Giszmo Addressed the tilt suggestion in 0e4524d. The camera now fits the torus silhouette to the playable area’s aspect ratio instead of forcing a steep view to keep the hole visible. This gives the front-facing landscape more room; wheel zoom still allows a closer view with cropped sides. The local square-tile mapping is unchanged. Updated actual renders, with map width × height:
Shallow angles also exposed precision loss when picking narrow projected triangles. The barycentric calculation now uses double precision, with coverage across portrait and wide windows, map shapes, and transitions. OpenGL and software-only builds/rendering, software-only startup with GPU requested, ASan/UBSan geometry/picking checks with FMA disabled, the terrain regression and all 158 CppUnit tests pass locally. The 256 × 256 rendering-only benchmark measured about 15.4 ms median with clouds on the M3 in this run. Master is merged through b47c7d2 in the separate merge commit e155753. The previous Linux/Windows CI run passed; new checks are running. Keeping the PR draft and automatic folding off by default. Agreed that 3D unit models belong in a separate PR; this one continues to reuse the sprite renderer. |
|
Can you render how 64x512 would look? I'd tilt the 512x64 much flatter. When you zoom out, you still care about what was the center of screen and in this case it drifts off very far. I assume the 64x512 case would need an extreme ellipsis rotated around the center instead of a circle. |














Draft while we continue integration testing and keep this branch current with
master.A rendering experiment that makes Glob2’s wrapping map visible as a live 3D torus. G explicitly switches between regular 2D and the optional torus view. Arrow keys, screen edges, the minimap and middle-drag navigate within the current mode; the wheel zooms within 3D. By default, ordinary scrolling never folds the map or snaps back. Main-menu Settings → General Settings → Automatic torus view enables gradual folding while scrolling and a quick return after movement stops; G keeps the overview open. The preference is saved locally and is inactive with software rendering. Normal 2D retains its viewport renderer, without full-world texture captures or torus mesh updates.
Following Giszmo’s feedback, this incorporates the feature changes from
feat/torus-panthroughb838f8de, with attribution to Bob. Both map axes slide around a ring whose orientation stays fixed. The star field follows horizontal navigation only: vertical movement rolls the map around the tube without tilting the sky. The camera tilt follows the playable area’s aspect ratio and favors the front-facing landscape over keeping the torus hole visible. The overview fits inside the playable area; wheel zoom can crop the sides for a closer view. Playtesting favored explicit mode switching as the default; automatic folding remains available as an opt-in preference. Both modes use the same renderer and performance fixes.Rendering and interaction
TorusView.cpp; OpenGL drawing and resource ownership live inTorusViewRender.cpp.Software rendering remains supported, including builds with
opengl=0and startup with GPU mode requested. Unsupported configurations retain 2D. Camera state is not saved or sent over the network.Large-map performance
Profiling Oazis (256 × 256) on an Apple M3 identified redundant full-world cloud generation, individual resource sprite draws, and per-sprite GPU state changes in the batching path. The capture now computes shadows only, with overview cloud sampling bounded to 128 cells per world axis. Variable-size resource frames use a padded atlas, and queued sprite draws set GPU state at batch submission. Normal 2D retains native detail and software rendering.
The overview texture cap is 4096 pixels per axis, reducing the 256 × 256 map’s color texture from 256 MiB to 64 MiB. The live map still refreshes every rendered frame. In 100-frame rendering benchmarks with GPU completion included, the torus improved from about 130 ms to 12–16 ms per frame with clouds. These measurements exclude simulation, HUD drawing and frame pacing. The optimized build has also been playtested locally.
Validation
Resource atlas comparisons cover every frame at three scales and two opacity levels, with zero pixel difference on macOS. A repeatable loaded-game performance benchmark is included. Synthetic 64 × 128, 512 × 64, 64 × 512 and square maps cover proportions, fitting, picking and map-dimension cache changes. The map-proportioned geometry measured 16.64 ms median / 17.87 ms p95 with clouds in a 150-frame Oazis run on the M3; desktop load affects these rendering-only measurements.
Local macOS validation covers OpenGL and software-only release builds, loaded-game rendering in both modes, cloud transitions, wrapped navigation, picking, explicit mode transitions, inactive torus controls during 2D navigation, explorer positions across viewport and atlas seams, automatic-mode timing and pinning, option persistence, keyboard conflicts, and repeated resource teardown/recreation. Geometry, picking, cloud-field and building-wrap tests pass AddressSanitizer/UndefinedBehaviorSanitizer.
CI builds Linux 22.04/24.04 and MinGW-w64 game/server targets and runs the standalone tests. Linux additionally exercises the loaded game through Mesa/Xvfb and SDL software rendering, builds without OpenGL, and checks startup and rendering with GPU mode requested. See the current PR checks for results on the latest commit.
Earlier demo
This recording shows the original manual camera experiment. It predates the fixed-axis scrolling behavior and rendering corrections above.
torus-demo-final.mp4
Scope and limitations
This draft tracks
masterthrough merge commits. The AI trainer/refactoring and fullscreen-scaling PRs have now landed inmasterand are included through that base. The torus is adapted to the new GUI/render modules, viewer state and pending building positions. Conflicts and CI will continue to be maintained while the PR stays draft. Giszmo's native Wayland setup still needs playtesting to verify the combined behavior.Compatibility OpenGL with shaders and framebuffer objects is required for 3D. Large maps may downsample at the 4096-pixel atlas cap and can cost more than ordinary 2D. Tile size varies around the tube and perspective foreshortens tiles, especially near the inner opening. Units/buildings remain sprites on the surface; unit picking uses map cells. Native Windows/Linux visual and broader gameplay testing remain useful.
Build instructions, architecture, tests and limitations.