lighting: fix long-standing issue with invisible objects#7901
lighting: fix long-standing issue with invisible objects#7901AJenbo merged 3 commits intodiasurgical:masterfrom
Conversation
|
Nice, this always bugged me. |
AJenbo
left a comment
There was a problem hiding this comment.
This may need a new time demo to be recorded to it to pass the tests.
|
@AJenbo pushed the change related to the
I'm not familiar with the development process here, not sure is clear to me what has to be done exactly. |
|
One of the test is an input recording that plays the two first levels in the shareware. The changes you have made here affects game play so the demo recording no longer syncs, since the change is intentional a new recording has to be made so that it matches the new behavior. This is done switching to the shareware mode, and copying the save from the test folder to your save folder, starting the game with the following arguments: |
|
Sweet, thanks for the explanation. I see that Are there any requirements for the demo? Like certain actions? I played back the original |
Seems to be because this PR completely breaks the timedemo recording, right from the start. I'm not entirely sure why it would do that, unless maybe the change to visibility causes a monster to wake up early and completely skew the sequence of random numbers. |
|
Here is a recording of the time demo from a couple of versions ago: https://www.youtube.com/watch?v=prPVymbw3t0 What you want is to trigger as many things as possible:
Note that you do not want to trigger time sensetive things like:
Once submitted you will be able to see if there is a significant difference in test coverage which will let you know if you did more or less things then the previous demo. |
Is that still an issue? I thought I fixed it. #6516 |
|
Oh i guess not, i suppose that's something we could improve in a new recording then. |
That's actually awesome. I made a side-by-side comparison: https://youtu.be/nhpuuHSKGgk . It all started with the first monster not being killed, then the player had to go to the left arch instead of the right one. Basically, this is a perfect illustration of the butterfly effect. And we can take the reasoning even further: how foresight (seeing of previously invisible objects) leads to death, how the amount of knowledge does not bring happiness, how curiosity becomes a curse :) I'll prepare the new timedemo. |
|
@AJenbo did the demo, now the test seems passes successfully, please take a look. |
|
Folks, while recording the demo on the latest master I noticed the bug with the health globe. The bug is well depicted on the video I've made: https://youtu.be/UIWqjRxAe3g?t=183 - starting from the 3:05, when the player got a new level, the health was restored, but the health globe reflects that in a weird way. Something known? |
|
Such an awesome change this is. Great stuff @rouming |
This seems like the same bug as #7835, except for the health globe rather than mana globe. |
Thanks, will post there then. |
|
Converting this to draft, will return to this PR in a couple of weeks. |
This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
|
Initially, I hoped to avoid adjusting the radius, but it turns out this isn't straightforward for any radius value passed to the |
This test covers a few vision bugs: 1. VisibilityInStraightLineOfSight - test case checks the visibility of objects in a straight line of sight parallel to the X or Y coordinate lines: diasurgical#7901 2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is visible through the diagonally adjacent tiles: diasurgical#7920 3. VisibleObjects - generic test, which makes sure some objects are visible, but some - are not. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This test covers a few vision bugs: 1. VisibilityInStraightLineOfSight - test case checks the visibility of objects in a straight line of sight parallel to the X or Y coordinate lines: diasurgical#7901 2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is visible through the diagonally adjacent tiles: diasurgical#7920 3. VisibleObjects - generic test, which makes sure some objects are visible, but some - are not. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This test covers a few vision bugs: 1. VisibilityInStraightLineOfSight - test case checks the visibility of objects in a straight line of sight parallel to the X or Y coordinate lines: #7901 2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is visible through the diagonally adjacent tiles: #7920 3. VisibleObjects - generic test, which makes sure some objects are visible, but some - are not. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This test covers a few vision bugs: 1. VisibilityInStraightLineOfSight - test case checks the visibility of objects in a straight line of sight parallel to the X or Y coordinate lines: diasurgical/DevilutionX#7901 2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is visible through the diagonally adjacent tiles: diasurgical/DevilutionX#7920 3. VisibleObjects - generic test, which makes sure some objects are visible, but some - are not. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
-----------------------------------------------------------------------------------------------------
chromebook-linux-audio.mk 7acadc46bad5363053874fa625a79314931ba1be # Version: Commits on Apr 21, 2025
-----------------------------------------------------------------------------------------------------
functions: extend chrome platform detection to check product_family,
--------------------------------------------------------------------------------------------------------
batocera-emulationstation.mk cff195416e194420cae771523a980c83afd600d4 # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------------------------
Merge pull request #1904 from Tovarichtch/patch-1
[lightgun] add pause menu to ghost squad (wii),
------------------------------------------------------------------------------------------------
batocera-es-piboy.mk cff195416e194420cae771523a980c83afd600d4 # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------------------
Merge pull request #1904 from Tovarichtch/patch-1
[lightgun] add pause menu to ghost squad (wii),
------------------------------------------------------------------------------------------
dolphin-emu.mk fd8ce3ce8062a911e9cb73a725b31df3ad99efa0 # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------------
Merge pull request #13555 from jordan-woyak/cubeb-default
AudioCommon: Make cubeb sound backend default on Linux.,
-------------------------------------------------------------------------------------
ikemen.mk 9bcc118d5d2468f933087db9db16d6655b5610e6 # Version: Commits on Apr 22, 2025
-------------------------------------------------------------------------------------
Merge pull request #2419 from Eiton/3d-stage
fix: model attribute,
--------------------------------------------------------------------------------------
openmsx.mk 1bc4ab8d0c625b8657840fd204db5686727d22fc # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------
Prepare init.tcl for Tcl9
This is a (small) part of:
openMSX/openMSX#1900
Tcl8 and Tcl9 are not 100% compatible, see:
https://core.tcl-lang.org/tcl/wiki?name=Migrating+scripts+to+Tcl+9
This only fixes `share/init.tcl` not any of the other scripts in
`share/scripts/*.tcl`. I don't expect many fixes wil be needed. I just
haven't checked yet (testing all scripts takes more time than I have
today).,
----------------------------------------------------
pcsx2.mk v2.3.291 # Version: Commits on Apr 22, 2025
----------------------------------------------------
- [CDVD: Adjust precache osd to display decimal value for required ram, adjust linux get available memory logic.](PCSX2/pcsx2#12554)
,
-------------------------------------------------------------------------------------
ppsspp.mk eacbbe0efdddf4ce39ebd387d5532ad99fc8dd7c # Version: Commits on Apr 22, 2025
-------------------------------------------------------------------------------------
Merge pull request #20282 from hrydgard/disable-qt-again
Specify the Qt version in CI,
------------------------------------------------------------------------------------
rpcs3.mk 5ca5b54bf6f01584bd5444f35b3e69d62d6c31a6 # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------
Fix sceNpTrophyRegisterContext,
---------------------------------------------------------------
ruffle.mk nightly-2025-04-22 # Version: Commits on Apr 22, 2025
---------------------------------------------------------------
## What's Changed
* build: Set a different channel for local builds by @kjarosh in ruffle-rs/ruffle#20173
* build(deps-dev): bump the npm-minor group in /web with 14 updates by @dependabot in ruffle-rs/ruffle#20237
* build(deps): bump the cargo-minor group with 3 updates by @dependabot in ruffle-rs/ruffle#20239
**Full Changelog**: ruffle-rs/ruffle@nightly-2025-04-20...nightly-2025-04-22,
----------------------------------------------------
ryujinx.mk 1.3.32 # Version: Commits on Apr 21, 2025
----------------------------------------------------
# Canary builds:
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/Ryubing/Stable-Releases/releases/latest) instead if that sounds like something you don't want to deal with.
| Platform | Artifact |
|--|--|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/Ryubing/Canary-Releases/releases/download/1.3.32/ryujinx-canary-1.3.32-win_x64.zip) |
| Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/Ryubing/Canary-Releases/releases/download/1.3.32/ryujinx-canary-1.3.32-win_arm64.zip) |
| Linux 64-bit | [Canary Linux Artifact](https://github.com/Ryubing/Canary-Releases/releases/download/1.3.32/ryujinx-canary-1.3.32-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/Ryubing/Canary-Releases/releases/download/1.3.32/ryujinx-canary-1.3.32-linux_arm64.tar.gz) |
| macOS | [Canary macOS Artifact](https://github.com/Ryubing/Canary-Releases/releases/download/1.3.32/ryujinx-canary-1.3.32-macos_universal.app.tar.gz) |
**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-1.3.31...Canary-1.3.32)**,
--------------------------------------------------------------------------------------
shadps4.mk 0c86c54d48533e3505e56e639059d28331fe4bc3 # Version: Commits on Apr 21, 2025
--------------------------------------------------------------------------------------
Implement SET_PC_B64 instruction (#2823)
* basic impl
* minor improvements
* clang
* more clang
* improvements requested by squidbus,
---------------------------------------------------------------------------------------
thextech.mk 44b4a2da29bd7c785775d727216a3890796cd9d1 # Version: Commits on Apr 21, 2025
---------------------------------------------------------------------------------------
Use layer speed of collided blocks and conveyor belts
Thanks to @Superbloxen for the report,
-------------------------------------------------
vice.mk r45634 # Version: Commits on Apr 22, 2025
-------------------------------------------------
Gtk3: Use \Play\ instead of \Start\ for datasette controls submenu
git-svn-id: https://svn.code.sf.net/p/vice-emu/code/trunk@45634 379a1393-f5fb-40a0-bcee-ef074d9b53f7,
-------------------------------------------------------------------------------------
vita3k.mk 0b4a4e58d18436f9f9631e7e50af101b3187e3c6 # Version: Commits on Apr 20, 2025
-------------------------------------------------------------------------------------
external: Fix link to pre-built OpenSSL by updating it to 3.5.,
-----------------------------------------------------------------------------------
xemu.mk 1a6b858fe83e6817ed8fa931ad591bf4922b65f2 # Version: Commits on Apr 21, 2025
-----------------------------------------------------------------------------------
ci: bump softprops/action-gh-release from 2.2.1 to 2.2.2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](softprops/action-gh-release@c95fe14...da05d55)
---
updated-dependencies:
- dependency-name: softprops/action-gh-release
dependency-version: 2.2.2
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>,
-------------------------------------------------------------------------------------------
xenia-native.mk 7566871220009780f8ac4488cef9620f5d97390d # Version: Commits on Apr 22, 2025
-------------------------------------------------------------------------------------------
[D3D12] Changed default resource state based on GPU Validation
- This prevents GBV from spamming warnings,
----------------------------------------------------------------------------------------
pironman5.mk 11c594d5d0ace7f64ac7e054dc6dfd2325b0d14d # Version: Commits on Apr 22, 2025
----------------------------------------------------------------------------------------
chore: update version to 1.2.6.1,
----------------------------------------------------------------------------------------------
ffmpeg-rockchip.mk 57d5befee96f229b05fa09334a4d7a6f95a324bd # Version: Commits on Apr 22, 2025
----------------------------------------------------------------------------------------------
fixup! lavc/rkmppenc: add UDU SEI support for H26x encoders
polish the udu-sei impl.
Signed-off-by: nyanmisaka <nst799610810@gmail.com>,
------------------------------------------------------------------------------------
box64.mk cc6500b7ddd633c3294225f433fe77caaf4473f9 # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------
[RBTREE] Fixed an edge case (#2562),
---------------------------------------------------------------------------------------
corsixth.mk 3c5b742857df63a9c7a1c7bd570b1034e065993d # Version: Commits on Apr 22, 2025
---------------------------------------------------------------------------------------
Merge pull request #2398 from tobylane/fontincluded
Look for a bundled Noto CJK font,
------------------------------------------------------------------------------------------
devilutionx.mk 9e05af66bd4866b4d49ad39ac9231929f2afe8bd # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------------
test: add `vision_test`
This test covers a few vision bugs:
1. VisibilityInStraightLineOfSight - test case checks the visibility
of objects in a straight line of sight parallel to the X or Y
coordinate lines:
diasurgical/DevilutionX#7901
2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is
visible through the diagonally adjacent tiles:
diasurgical/DevilutionX#7920
3. VisibleObjects - generic test, which makes sure some objects are
visible, but some - are not.
Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>,
---------------------------------------------------------------------------------------
etlegacy.mk f50cc647facda20edefca0edd2cdce7892684539 # Version: Commits on Apr 22, 2025
---------------------------------------------------------------------------------------
game: fix c90 standard violations,
-------------------------------------------------------------------------------------------
jazz2-native.mk 9a3418bcfe12b559b90c7bb92b539a46445dc42f # Version: Commits on Apr 22, 2025
-------------------------------------------------------------------------------------------
Multiplayer, renamed \IsElimination\ to \Elimination\, fixed MovingPlatform,
--------------------------------------------------------------------------------------
omf2097.mk e1c9fb24cde7c7334ccaaea2fff467b7926f10f5 # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------
Projectile behavior fixes (#1212)
* Projectile hit behavior fixes
* Fix shredder hands not able to combo
* Fix Electra's projectile not being controllable in hyper mode,
----------------------------------------------------------------------------------
stk.mk 79df88bdd3316e89bf004905313c2fc07e97d82f # Version: Commits on Apr 21, 2025
----------------------------------------------------------------------------------
Fix gles ibl shader,
----------------------------------------------------------------------------------------
supertux2.mk 3cddf3d41a3e3639bb6f2b7cf8099f0c5a2e3604 # Version: Commits on Apr 21, 2025
----------------------------------------------------------------------------------------
re-export test tiles [ci skip],
----------------------------------------------------------------------------------------
hid-tmff2.mk d4c9e065ca41b30e1cb7a9852ba182b53a669b9c # Version: Commits on Apr 22, 2025
----------------------------------------------------------------------------------------
Merge pull request #156 from danielpokladek/patch-1
Adds reminder to add MOK certificate if using Secure Boot + DKMS.,
----------------------------------------------------------------------------------------
retroarch.mk 03525ffd5f179b60e996dfc1d91dde82c62b27c2 # Version: Commits on Apr 22, 2025
----------------------------------------------------------------------------------------
Fetch translations from Crowdin,
----------------------------------------------------------------------------------------
doomretro.mk b469ac9bdb5624fad0b55dd6ac00e1696da03b23 # Version: Commits on Apr 21, 2025
----------------------------------------------------------------------------------------
Fix previous commit for CMake,
-----------------------------------------------------------------------------------
tr1x.mk 0adefabf41f36392c9810f60028a84d90a6bb702 # Version: Commits on Apr 22, 2025
-----------------------------------------------------------------------------------
data: use HD assets,
-----------------------------------------------------------------------------------
tr2x.mk 0adefabf41f36392c9810f60028a84d90a6bb702 # Version: Commits on Apr 22, 2025
-----------------------------------------------------------------------------------
data: use HD assets,
---------------------------------------------------------------------------------------------------
libretro-dosbox-pure.mk 2bd477b2eaff7a3d34b31b12487a29ae4b79e6f3 # Version: Commits on Apr 22, 2025
---------------------------------------------------------------------------------------------------
Make IMGMOUNT drives accessible in disc control menu (#594)
This is done by sharing DOSBox's DriveManager state with DOSBox Pure's disk image management. It is not elegant due to the two different approaches being forced to work together. It would be better to remove DriveManager and just have a single disk mounting system.,
--------------------------------------------------------------------------------------------------
libretro-gearcoleco.mk 18ad36be7a9fe6c57205ee0765290e9a91ceadd8 # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------------------
[libretro] Fix Android build,
--------------------------------------------------------------------------------------------------
libretro-gearsystem.mk 479d38c54e59e8de943752f75153808c09f505da # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------------------
[libretro] Redirect emu log to libretro log,
----------------------------------------------------------------------------------------------
libretro-ppsspp.mk eacbbe0efdddf4ce39ebd387d5532ad99fc8dd7c # Version: Commits on Apr 22, 2025
----------------------------------------------------------------------------------------------
Merge pull request #20282 from hrydgard/disable-qt-again
Specify the Qt version in CI,
--------------------------------------------------------------------------------------------
libretro-puae.mk 7dd724eaa48f05f02d9d2f1bfa131c34b6ab5351 # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------------
Fix archived HDF temp cleanup,
------------------------------------------------------------------------------------------------
libretro-puae2021.mk 87cbcb27809c2800418bf81da21a766de28029a0 # Version: Commits on Apr 22, 2025
------------------------------------------------------------------------------------------------
Fix archived HDF temp cleanup,
---------------------------------------------------------------------------------------------
libretro-vba-m.mk 9e724ea4b8e5298d3b096daac1df59e997f18c40 # Version: Commits on Apr 22, 2025
---------------------------------------------------------------------------------------------
build: support building ARM64 binary for Mac
Make some adjustments to the Mac build scripts to support building an
ARM64 binary for Apple Silicon.
Also support cross-compiling for Intel on Apple Silicon.
Also prefer using Ninja for CMake ports.
Signed-off-by: Rafael Kitover <rkitover@gmail.com>,
--------------------------------------------------------------------------------------------
libretro-vice.mk e5b036f0be19f7a70fde75cc0e8b1b43476adc13 # Version: Commits on Apr 22, 2025
--------------------------------------------------------------------------------------------
Unload-deinit cleanup,
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
This test covers a few vision bugs: 1. VisibilityInStraightLineOfSight - test case checks the visibility of objects in a straight line of sight parallel to the X or Y coordinate lines: diasurgical#7901 2. NoVisibilityThroughAdjacentTiles - test case checks that nothing is visible through the diagonally adjacent tiles: diasurgical#7920 3. VisibleObjects - generic test, which makes sure some objects are visible, but some - are not. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
…#7901) * lighting: fix long-standing issue with invisible objects This fixes an issue with lighting, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. Issue diasurgical#6641 perfectly illustrates the bug (see video attached to the bug). What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines. The actual bug lies in the visibility checks of adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case: #? ↗ # x The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer. The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible. For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug. To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines. To better demonstrate the problem, here's a straightforward simulation written in Python: https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5 The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles, '.' are marked as visible, were hit by the cast rays. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines. In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly. Fixes: diasurgical#6641 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * lighting: rename variables and add explicit comments for clarity This patch improves clarity and readability without affecting functionality: 1. Renames `VisionCrawlTable` to `VisionRays` and `crawl` to `rayPoint` for better clarity on the purpose of these structures. 2. Renames `factors` to `quadrants` to reflect the actual purpose of the mirror operation along the X or Y coordinate lines. 3. Adds more explicit comments to simplify the understanding of the ray casting algorithm. Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> * test/WarriorLevel1to2: update timedemo Recent visibility fix impacts game state and causes the timedemo to behave completely differently, resulting in a butterfly effect: https://youtu.be/nhpuuHSKGgk. This patch updates the timedemo, which was recorded with the visibility fixes applied, ensuring the tests pass successfully. Here's the latest timedemo video for the future generations: https://youtu.be/udGcWmarYNI Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> --------- Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 88d0cb7)
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> (cherry picked from commit 5226d55)
This PR fixes an issue with visibility, where objects in a straight line of sight parallel to the X or Y coordinate lines become invisible. The #6641 is a perfect illustration of the bug.
What's worse, the objects are invisible to the observer (player) regardless of the distance to that objects. The main requirement of a bug reproduction is line of sight parallel to the X or Y coordinate lines.
The actual bug lies in the visibility checks of diagonally adjacent tiles of a point, hit by the cast ray. We've cast an approximated ray on an integer 2D grid, so we need to check if a ray can pass through the diagonally adjacent tiles. For example, consider this case:
The ray is cast from the observer 'x', and reaches the '?', but diagonally adjacent tiles '#' do not pass the light, so the '?' should not be visible for the 2D observer.
The trick is to perform two additional visibility checks for the diagonally adjacent tiles, but only for the rays that are not parallel to the X or Y coordinate lines. Parallel rays, which have a 0 in one of their coordinate components, do not require any additional adjacent visibility checks, and the tile, hit by the ray, is always considered visible.
For the rays that parallel to the X or Y coordinate lines, the adjacent visibility check always degenerated to the actual ray point visibility check, which is considered invisible if it does not allow light to pass through, and this is the actual bug.
To fix the issue, ensure the tile is always considered visible if the ray that hits it is parallel to the X or Y coordinate lines.
To better demonstrate the problem, here's a straightforward simulation written in Python:
https://gist.github.com/rouming/25c555720f93735442c2053426e73bf5
The code simulates lighting from the DevilitionX implementation, by placing the observer 'x' in the center of the grid. The observer is surrounded by walls and 5 random obstacles. Tiles, marked as '.' are visible tiles, depict, how rays spread around the observer. The first matrix output shows the bug: no walls and obstacles are visible in the line of sight parallel to the X and Y coordinate lines.
In contrast, the second matrix output (with the fix applied) does not exhibit this problem. Also, note the box corners are not visible due to the adjacent visibility checks, which are functioning correctly.