Difference between revisions of "Portal Placement"

From P2SR Wiki

m (Fixed typo)
 
(12 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{P2 Title|Portal Placement}}
 
{{P2 Title|Portal Placement}}
 
=Overview=
 
=Overview=
 +
[[File:Portal_Placement_Flowchart.png|1000px]]
 +
 
'''Portal placement''' is a process that can be split up into four steps:
 
'''Portal placement''' is a process that can be split up into four steps:
# '''Bullet ray cast''' - an initial step of shooting a portal and finding what surface has been hit.
+
# '''[[Portal Placement#Bullet Ray Cast|Bullet Ray Cast]]''' - an initial step of shooting a portal and finding what surface has been hit.
# '''Pre-bumping verification''' - checking if ''hit surface'' is viable for portal placement.
+
# '''[[Portal Placement#Pre-Bumping Verification|Pre-Bumping Verification]]''' - checking if ''hit surface'' is viable for portal placement.
# '''Bumping''' - attempting to fit the portal around other portals and edges.
+
# '''[[Portal Placement#Bumping|Bumping]]''' - attempting to fit the portal around other portals and edges.
# '''Post-bumping verification''' - checking if ''bumped position'' is viable for portal placement.
+
# '''[[Portal Placement#Post-Bumping Verification|Post-Bumping Verification]]''' - checking if ''bumped position'' is viable for portal placement.
 
This article will attempt to explain all of these steps, as well as mention all of the glitches and techniques related to them.
 
This article will attempt to explain all of these steps, as well as mention all of the glitches and techniques related to them.
  
 
=Bullet Ray Cast=
 
=Bullet Ray Cast=
 +
 
At the moment of shooting a portal, a ray is being traced with following parameters:
 
At the moment of shooting a portal, a ray is being traced with following parameters:
 
* It's traced from the current player's eye position towards the current eye looking direction, transformed by linked portals matrix if peeking through ones. Keep in mind that in some cases the player's eye position and rotation is not always equal to the player's camera position and rotation - for instance, shaking changes camera position but not eye position.
 
* It's traced from the current player's eye position towards the current eye looking direction, transformed by linked portals matrix if peeking through ones. Keep in mind that in some cases the player's eye position and rotation is not always equal to the player's camera position and rotation - for instance, shaking changes camera position but not eye position.
* The length of the ray is equal to 2<sup>15</sup> * √3, which covers the maximum distance between two points within the bounds of Source's map.<ref>This info has no application, making it useless. In most cases, it's easier to assume the ray is cast infinitely forward.</ref>
+
* The length of the ray is equal to 2<sup>15</sup>√3, which covers the maximum distance between two points within the bounds of Source's map.<ref>This info has no application, making it useless. In most cases, it's easier to assume the ray is cast infinitely forward.</ref>
* It hits surfaces marked as solid, ignoring (as in "shooting through") following entities:
+
* It hits surfaces marked as solid, ignoring (as in "shooting through") the following entities:
<code>prop_physics</code>, <code>prop_weighted_cube</code>, <code>prop_monster_box</code>, <code>func_physbox</code>, <code>npc_portal_turret_floor</code>, <code>prop_energy_ball</code>, <code>npc_security_camera</code>, <code>simple_physics_prop</code>, <code>simple_physics_brush</code>, <code>prop_ragdoll</code>, <code>prop_glados_core</code>, <code>player</code>, <code>Player</code><ref>Yes, the filter has two player classes implemented with uppercase and lowercase P. No idea why.</ref>, <code>projected_wall_entity</code>, <code>prop_paint_bomb</code>, <code>prop_exploding_futbol </code> and <code>npc_personality_core</code>.
+
<code>prop_physics</code>,
 +
<code>prop_weighted_cube</code>,
 +
<code>prop_monster_box</code>,
 +
<code>func_physbox</code>,
 +
<code>npc_portal_turret_floor</code>,
 +
<code>prop_energy_ball</code>,
 +
<code>npc_security_camera</code>,
 +
<code>simple_physics_prop</code>,
 +
<code>simple_physics_brush</code>,
 +
<code>prop_ragdoll</code>,
 +
<code>prop_glados_core</code>,
 +
<code>player</code>,
 +
<code>Player</code><ref>Yes, the filter has two player classes implemented with uppercase and lowercase P. No idea why.</ref>,
 +
<code>projected_wall_entity</code>,
 +
<code>prop_paint_bomb</code>,
 +
<code>prop_exploding_futbol</code> and
 +
<code>npc_personality_core</code>.
  
The tracing does go through portals, but it's stopped on the first hit prop_portal. This means that it's possible to shoot portals through world portals just fine, but shooting a prop_portal results in hitting a surface on which it's placed.
+
The tracing does go through portals, but stops if it hits a prop_portal. This means that it's possible to shoot portals through world portals just fine, but shooting a prop_portal results in hitting the surface on which it's placed.
  
Then, if ray does hit something, presumable angles for placed portal are calculated. If hit surface is a floor or a ceiling, then the ray direction is used as an up vector, resulting in the top of the portal oriented away from the player. If it's not a floor nor a ceiling, then player's up vector is used, resulting in the portal rotated upright.<ref>Upright meaning vector directed towards positive Z. This changes only when interacting with sticky gel (seems to work differently in P2:CE)</ref>
+
Then, if the ray does hit something, presumable angles for the placed portal are calculated.
 +
 
 +
* If the hit surface is a floor or a ceiling, then the ray direction is used as an up vector, resulting in the top of the portal oriented away from the player.
 +
 
 +
* Otherwise, the player's up vector is used, resulting in the portal being rotated upright.<ref>Upright meaning vector directed towards positive Z. This changes only when interacting with sticky gel (seems to work differently in P2:CE)</ref>
  
 
From there, the game uses the portal's origin (ray cast hit point) and its rotation for further checks.
 
From there, the game uses the portal's origin (ray cast hit point) and its rotation for further checks.
  
=Pre-bumping Verification=
+
=Pre-Bumping Verification=
 +
 
 +
Once a surface is hit and both portal's origin and angles are calculated, the following check is done:
 +
* If there's a portal belonging to player's coop partner that would overlap placed portal, the partner's portal is fizzled.
 +
 
 +
Then, if any of the following checks are true, portal placement is cancelled.
 +
# If the portal wouldn't be placed on something solid. This is checked using a raycast from 1 unit away from the portal, going 2 units toward the portal.
 +
# If the hit surface is moving and <code>sv_allow_mobile_portals</code> cvar is not enabled.
 +
# If the hit surface is a pass-through or non-portalable material.
  
Once a surface is hit and both portal's origin and angles are calculated, a set of checks and fixes are applied to them:
+
As a result of this ordering, it is possible to fizzle your partner's portal without placing one yourself.
# If there's a portal belonging to player's coop partner that would overlap placed portal, partner's portal is fizzled.
 
# A ray is casted 1 unit away from the origin, two units towards the surface of a portal, to see if portal would be placed on something solid. If it wouldn't, portal placement is cancelled.
 
# The surface is checked if it's moving. If it does and <code>sv_allow_mobile_portals</code> cvar is not enabled, placement is cancelled.
 
# The surface is checked if it's a pass-through or non-portallable material. If it is, placement is cancelled.
 
  
 
=Bumping=
 
=Bumping=
 +
 
==Portal Bumping==
 
==Portal Bumping==
TBW
+
 
 +
Portal bumping occurs only when portal is placed by a player and <code>sv_portal_placement_never_bump</code> is not active.
 +
 
 +
The game iterates through every active portal lying on the same surface and then checks the distance between them. This is done by measuring the length of a distance vector projected onto the right and up directional vectors of currently placed portal, and then comparing them to the width and height of the portal respectively. If both of them are smaller, the origin of a portal is moved so the length of a distance vector projected onto right directional vector would match a width of a portal, plus 1 unit. This works perfectly for portals placed on walls, because the logic works the same as just checking if portals are overlapping and moving the origin left or right so they don't overlap anymore, but when placing on floors or ceilings, portals can have different orientation, which can cause this algorithm to fail and not bump the portal far enough for placement to be successful.
 +
 
 +
For uses of portal bumping in routing, see [[Portal_Placement_Tricks#Portal_Bumping]].
 +
 
 
==Edge Bumping==
 
==Edge Bumping==
TBW
+
 
 +
Edge bumping is a part where the game determines if and how portal fits on a shot surface. If it fails to fit it, the portal placement is cancelled.
 +
 
 +
First, portal corners are calculated. Because of the "bump forgiveness", corner points are moved 2 units in each direction towards the middle of a portal. Thanks of that, it's possible to place a portal 2 units within a wall on each side. Then, for each corner we haven't intersected with yet, corner check algorithm is executed.
 +
After that, depending on what corners have been intersected, certain checks are being made to determine the viability of the surface.
 +
 
 +
<pre style="color:red">TODO: This section is not finished. Explain all cases implemented in the code.</pre>
 +
 
 +
Whole algorithm is repeated until surface is determined to be either portalable or non-portalable.
 +
 
 
===Corner check algorithm===
 
===Corner check algorithm===
TBW
+
 
=Post-bumping Verification=
+
For each corner of a portal, four checks are made: surface solidity, enclosing walls, bumping entities and surface portalability.
 +
 
 +
The way surface is checked if it's solid is quite interesting. A loop goes through 20 points evenly placed between the origin point (exclusive) and corner point (inclusive), moved 1 unit into the surface, and checks if they all lie within a solid object. This means that, as long as these 20 points are covered in something solid for each corner, surface can be considered viable, even though solid surface is missing everywhere else.
 +
 
 +
Enclosing wall check makes a simple ray trace from the origin to the corner, one unit away from the surface, to see if there are walls blocking the surface.
 +
 
 +
Bumping entities check makes a similar operation, but exclusively for entities meant to bump a portal, like <code>func_portal_bumper</code> or fizzlers.
 +
 
 +
A check for portalable surfaces is another interesting one. If portalable surface is not found on a corner point, a binary search is made to determine the point where non-portalable surface becomes portalable. However, if corner point does have a portalable surface, this check is completely skipped. This means that as long as origin point and corner points contain a portalable surface, it is possible to place a portal on them.
 +
 
 +
=Post-Bumping Verification=
 +
 
 
After the origin point is affected by all of the bumping and it's still viable for placement, a second set of checks and corrections are made:
 
After the origin point is affected by all of the bumping and it's still viable for placement, a second set of checks and corrections are made:
 +
 +
These checks are done, and if any are true, placement is cancelled:
 +
# If the origin point or any corner point is not next to solid, non-pass-through, portalable material.
 +
# If bumped portal origin has been moved more than a maximum bumping distance away from the original origin point (<code>√((portalWidth<sup>2</sup> + portalHeight<sup>2</sup>) / 2)</code> units, ~91.214 for default portal size).
 +
 +
Then the following correction is made:
 
# If a portal is closer to being vertical than horizontal (Z component of normalized portal's up vector is bigger than 0.7) and there’s a floor less than 1.5 units below the lower edge of a portal, adjusts the origin so the lower edge matches the floor position. This has been justified as ''helping game movement code run smoothly''.
 
# If a portal is closer to being vertical than horizontal (Z component of normalized portal's up vector is bigger than 0.7) and there’s a floor less than 1.5 units below the lower edge of a portal, adjusts the origin so the lower edge matches the floor position. This has been justified as ''helping game movement code run smoothly''.
# Placement is cancelled if portal would overlap the no-portal volume.
+
 
# Placement is also callened if portal would still overlap any other portals.
+
And then, if any of these checks are true, placement is cancelled:
# If player is in a portal that is about to be replaced and the new position is close to the original one, placement is cancelled. This has been justified as a fix for a "vert hop exploit".<ref>No idea what it could mean, but most likely not ground reportal, as that wouldn't fix it.</ref>
+
# If the portal would overlap a <code>no-portal</code> volume.
 +
# If the portal would still overlap any other portals.
 +
# If player is in a portal that is about to be replaced and the new position is close to the original one. This has been justified as a fix for a "vert hop exploit".<ref>No idea what it could mean, but most likely not ground reportal, as that wouldn't fix it.</ref>
  
 
If everything is okay by this point, successful placement state is returned and portal is placed.
 
If everything is okay by this point, successful placement state is returned and portal is placed.
  
 
=Related glitches=
 
=Related glitches=
TBW
+
 
==Portal Bumping==
+
See main page: [[Portal Placement Tricks]].
TBW
+
 
==Portal Edge Glitch==
 
TBW
 
 
==Portal Cut==
 
==Portal Cut==
 +
 
TBW
 
TBW
 +
 
==Obscure placement scenarios==
 
==Obscure placement scenarios==
 +
 
TBW
 
TBW
  
 
=References=
 
=References=
 
<references />
 
<references />

Latest revision as of 07:08, 29 December 2021

Portal Placement

Overview

Portal Placement Flowchart.png

Portal placement is a process that can be split up into four steps:

  1. Bullet Ray Cast - an initial step of shooting a portal and finding what surface has been hit.
  2. Pre-Bumping Verification - checking if hit surface is viable for portal placement.
  3. Bumping - attempting to fit the portal around other portals and edges.
  4. Post-Bumping Verification - checking if bumped position is viable for portal placement.

This article will attempt to explain all of these steps, as well as mention all of the glitches and techniques related to them.

Bullet Ray Cast

At the moment of shooting a portal, a ray is being traced with following parameters:

  • It's traced from the current player's eye position towards the current eye looking direction, transformed by linked portals matrix if peeking through ones. Keep in mind that in some cases the player's eye position and rotation is not always equal to the player's camera position and rotation - for instance, shaking changes camera position but not eye position.
  • The length of the ray is equal to 215√3, which covers the maximum distance between two points within the bounds of Source's map.[1]
  • It hits surfaces marked as solid, ignoring (as in "shooting through") the following entities:

prop_physics, prop_weighted_cube, prop_monster_box, func_physbox, npc_portal_turret_floor, prop_energy_ball, npc_security_camera, simple_physics_prop, simple_physics_brush, prop_ragdoll, prop_glados_core, player, Player[2], projected_wall_entity, prop_paint_bomb, prop_exploding_futbol and npc_personality_core.

The tracing does go through portals, but stops if it hits a prop_portal. This means that it's possible to shoot portals through world portals just fine, but shooting a prop_portal results in hitting the surface on which it's placed.

Then, if the ray does hit something, presumable angles for the placed portal are calculated.

  • If the hit surface is a floor or a ceiling, then the ray direction is used as an up vector, resulting in the top of the portal oriented away from the player.
  • Otherwise, the player's up vector is used, resulting in the portal being rotated upright.[3]

From there, the game uses the portal's origin (ray cast hit point) and its rotation for further checks.

Pre-Bumping Verification

Once a surface is hit and both portal's origin and angles are calculated, the following check is done:

  • If there's a portal belonging to player's coop partner that would overlap placed portal, the partner's portal is fizzled.

Then, if any of the following checks are true, portal placement is cancelled.

  1. If the portal wouldn't be placed on something solid. This is checked using a raycast from 1 unit away from the portal, going 2 units toward the portal.
  2. If the hit surface is moving and sv_allow_mobile_portals cvar is not enabled.
  3. If the hit surface is a pass-through or non-portalable material.

As a result of this ordering, it is possible to fizzle your partner's portal without placing one yourself.

Bumping

Portal Bumping

Portal bumping occurs only when portal is placed by a player and sv_portal_placement_never_bump is not active.

The game iterates through every active portal lying on the same surface and then checks the distance between them. This is done by measuring the length of a distance vector projected onto the right and up directional vectors of currently placed portal, and then comparing them to the width and height of the portal respectively. If both of them are smaller, the origin of a portal is moved so the length of a distance vector projected onto right directional vector would match a width of a portal, plus 1 unit. This works perfectly for portals placed on walls, because the logic works the same as just checking if portals are overlapping and moving the origin left or right so they don't overlap anymore, but when placing on floors or ceilings, portals can have different orientation, which can cause this algorithm to fail and not bump the portal far enough for placement to be successful.

For uses of portal bumping in routing, see Portal_Placement_Tricks#Portal_Bumping.

Edge Bumping

Edge bumping is a part where the game determines if and how portal fits on a shot surface. If it fails to fit it, the portal placement is cancelled.

First, portal corners are calculated. Because of the "bump forgiveness", corner points are moved 2 units in each direction towards the middle of a portal. Thanks of that, it's possible to place a portal 2 units within a wall on each side. Then, for each corner we haven't intersected with yet, corner check algorithm is executed. After that, depending on what corners have been intersected, certain checks are being made to determine the viability of the surface.

TODO: This section is not finished. Explain all cases implemented in the code.

Whole algorithm is repeated until surface is determined to be either portalable or non-portalable.

Corner check algorithm

For each corner of a portal, four checks are made: surface solidity, enclosing walls, bumping entities and surface portalability.

The way surface is checked if it's solid is quite interesting. A loop goes through 20 points evenly placed between the origin point (exclusive) and corner point (inclusive), moved 1 unit into the surface, and checks if they all lie within a solid object. This means that, as long as these 20 points are covered in something solid for each corner, surface can be considered viable, even though solid surface is missing everywhere else.

Enclosing wall check makes a simple ray trace from the origin to the corner, one unit away from the surface, to see if there are walls blocking the surface.

Bumping entities check makes a similar operation, but exclusively for entities meant to bump a portal, like func_portal_bumper or fizzlers.

A check for portalable surfaces is another interesting one. If portalable surface is not found on a corner point, a binary search is made to determine the point where non-portalable surface becomes portalable. However, if corner point does have a portalable surface, this check is completely skipped. This means that as long as origin point and corner points contain a portalable surface, it is possible to place a portal on them.

Post-Bumping Verification

After the origin point is affected by all of the bumping and it's still viable for placement, a second set of checks and corrections are made:

These checks are done, and if any are true, placement is cancelled:

  1. If the origin point or any corner point is not next to solid, non-pass-through, portalable material.
  2. If bumped portal origin has been moved more than a maximum bumping distance away from the original origin point (√((portalWidth2 + portalHeight2) / 2) units, ~91.214 for default portal size).

Then the following correction is made:

  1. If a portal is closer to being vertical than horizontal (Z component of normalized portal's up vector is bigger than 0.7) and there’s a floor less than 1.5 units below the lower edge of a portal, adjusts the origin so the lower edge matches the floor position. This has been justified as helping game movement code run smoothly.

And then, if any of these checks are true, placement is cancelled:

  1. If the portal would overlap a no-portal volume.
  2. If the portal would still overlap any other portals.
  3. If player is in a portal that is about to be replaced and the new position is close to the original one. This has been justified as a fix for a "vert hop exploit".[4]

If everything is okay by this point, successful placement state is returned and portal is placed.

Related glitches

See main page: Portal Placement Tricks.

Portal Cut

TBW

Obscure placement scenarios

TBW

References

  1. This info has no application, making it useless. In most cases, it's easier to assume the ray is cast infinitely forward.
  2. Yes, the filter has two player classes implemented with uppercase and lowercase P. No idea why.
  3. Upright meaning vector directed towards positive Z. This changes only when interacting with sticky gel (seems to work differently in P2:CE)
  4. No idea what it could mean, but most likely not ground reportal, as that wouldn't fix it.