I am trying to implement Doom’s Visportal Occlusion system in Unity: https://www.iddevnet.com/doom3/visportals.php
As the link states, the goal is to perform “unions of the screen space rectangles between the areas”. However, since the rectangles, or visportals, exist in the 3D world, a method of projecting them into the screen space is necessary, and Camera.WorldToScreenPoint method seemed perfect for it.
So first, I was able to achieve this:
The lines are drawn with GL_LINES, in the screen space by using the WorldToScreenPoint method in each of the visportal’s corners.
However, due to how the method works, looking at the portal in different angles makes some corners go behind the camera, producing unwanted results:
In this example, the left bottom corner of the visportal, because it is behind the camera, gets wrapped around, which makes the resulting shape unusable for further calculations.
So how can I bypass this? How can I turn a 3D “Rectangle” in the world and convert it into a 2D version, flattened into screen space?
One solution i can come up with is cutting the rectangle straight by the screen, achieving a shape like this:
But I have no idea how to implement this, especially since rotating the camera makes the conversion tend to infinite…
After receiving such great responses, I decided to add a link for a sample project containing my current implementation. If anybody thinks he can provide with improvements and feedback, feel free!
Basically, each visportal knows both rooms it is linking, and each room knows every visportal it contains.
For now, each room has a trigger collider so that I know where the player is. I do not love this approach, especially since unity’s callbacks aren’t always reliable, but it will do for now.
Then, for each room where player is, I call a recursive method which continuously performs polygon clipping with the help of the Clipper library (http://www.angusj.com/delphi/clipper.php).
If there is a solution, the method shows the room in which the player is not (so if im in room A and visportal connects A and B, I want to show room B), and recalls itself for each portal of the new visible room.
If you approach a portal and rotate the camera, you will see the problem deriving from Camera.WorldToScreenPoint, where a corner will go to the other side, due to the wrapping.
I hope this can be of use to somebody