Position: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Framed images)
m (Text replacement - "{{Feature | Important | " to "{{Feature|important|")
 
(30 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{TOC|side}}
{{TOC|side}}
== Introduction ==
Positions in {{arma}} games are always represented as [[Array|arrays]]. There are two types of positions:
Positions in Arma are always represented as [[Array|arrays]]. There are two types of positions:
* 2D position: {{hl|[X, Y]}}
* 2D positions: <tt>[X, Y]</tt>
* 3D position: {{hl|[X, Y, Z]}}
* 3D positions: <tt>[X, Y, Z]</tt>
On the map, the X-axis runs from west to east and the Y-axis runs from south to north. The origin <tt>[0, 0]</tt> is (usually) located in the bottom left corner.<br>
While the Z-coordinate is always the height, the point relative to which that height is measured depends on the specific position format (see below).


{{Informative|Since Arma 3 v1.93.145664: X, Y and Z are limited to values between -50km and +500km.}}
On the map and on the terrain, the X-axis runs from west to east and the Y-axis runs from south to north. The origin {{hl|[0, 0]}} is (usually) located in the bottom left corner.<br>
While the Z-coordinate is always the height/altitude, the point relative to which that height is measured depends on the specific position format (see {{Link|#Types}} below).


== Formats ==
{{Feature|arma3|Since {{arma3}} v1.94: X, Y and Z are limited to values between -50km and +500km. Using any '''setPos*''' command with values greater than that will {{Link|https://en.wikipedia.org/wiki/Clamping_(graphics)|clamp}} the value to within these boundaries, not throwing any errors. e.g:
[[Image:position.jpg|right|thumb|A comparison of the most common formats]]
<sqf>player setPosASL [-50001, 500001, 500001]; // player will be set to [-50000, 500000, 500000]</sqf>}}
 
 
== Commands ==
 
See:
* [[:Category:Command Group: Positions|Command Group: Positions]]
* [[:Category:Command Group: Render Time Scope|Command Group: Render Time Scope]]
 
 
== Types ==
 
[[File:position.jpg|right|thumb|400px|A comparison of most common formats, where each curve shows the reference height (Z = 0) for that format. Notice that the ASL format is absolute, i.e. its reference height doesn't change from one place to another, unlike other formats. For example, an object on a mountain and an object at the bottom of the sea both have an ATL height equal to 0.]]
There are a number of formats available in [[Real Virtuality]]:
There are a number of formats available in [[Real Virtuality]]:
{|
{|
|-
| '''ASL:''' || Presumably "'''A'''bove '''S'''ea '''L'''evel"
| '''ASL:''' || Presumably "'''A'''bove '''S'''ea '''L'''evel"
|-
|-
Line 30: Line 39:
| '''Config:''' || Position used in configs
| '''Config:''' || Position used in configs
|-
|-
| '''Object:''' || When object is used for position, [[PositionWorld]] of the object is used
| '''Object:''' || When object is used for position, [[Position#PositionWorld|PositionWorld]] of the object is used
|-
| '''Visual:''' || Used for rendering objects on the screen. Useful for per-frame applications, such as [[drawIcon3D]] - see [[:Category:Command Group: Render Time Scope|Command Group: Render Time Scope]] and [[Simulation vs Render Time Scope]].
|}
|}
<br>
{{Feature|important|Note that the only '''absolute position format''' in Arma for 3D calculations is the ASL format. Always pay attention to this fact when performing 3D calculations. For example, when a unit is climbing a mountain, the Z in ATL format is '''always 0'''. The following example demonstrates this behavior:<br>
Let's say it is desired to see if there is an intersection between two horizontal positions:
<sqf>
private _pos1 = getPosATL _unit;
private _pos2 = _pos1 vectorAdd [0,200,0]; // make a horizontal line by shifting the y, so z remains the same
private _intersects = lineIntersects [ATLToASL _pos1, ATLToASL _pos2]; // lineIntersects needs ASL, so we just convert _pos1 and _pos2 to ASL...
</sqf>
However, this is incorrect. ATL is a relative format, and while the ATL height between the coordinates is the same, the ASL height might not be (think of the mountain example again). <br>
This is the correct way to write the above code:
<sqf>
private _pos1 = getPosASL _unit;
private _pos2 = _pos1 vectorAdd [0,200,0]; // make a horizontal line by shifting the y
private _intersects = lineIntersects [_pos1, _pos2];
</sqf>
}}
=== Position2D ===
This array only has two elements and is usually used with 2D information, for example standard markers or UI commands. If used with e.g [[distance]], Z is assumed to be 0.
=== PositionASL ===


== PositionASL ==
Z is measured from the sea level which is constant across the map.
Z is measured from the sea level which is constant across the map.


Line 39: Line 71:
[[getPosASL]], [[setPosASL]], [[getPosASLVisual]], [[visiblePositionASL]], [[ASLToATL]], [[ATLToASL]], [[AGLToASL]], [[ASLToAGL]], [[eyePos]], [[aimPos]], [[getTerrainHeightASL]], [[lineIntersects]], [[lineIntersectsWith]], [[lineIntersectsObjs]], [[lineIntersectsSurfaces]], [[terrainIntersectASL]], [[playSound3D]], [[setDefaultCamera]]
[[getPosASL]], [[setPosASL]], [[getPosASLVisual]], [[visiblePositionASL]], [[ASLToATL]], [[ATLToASL]], [[AGLToASL]], [[ASLToAGL]], [[eyePos]], [[aimPos]], [[getTerrainHeightASL]], [[lineIntersects]], [[lineIntersectsWith]], [[lineIntersectsObjs]], [[lineIntersectsSurfaces]], [[terrainIntersectASL]], [[playSound3D]], [[setDefaultCamera]]


== PositionASLW ==
=== PositionASLW ===
Z is measured from the surface of the sea that could be higher or lower than sea level due to waves.
 
Z is measured from the surface of water at that position. Both waves and pond objects affect the result.


'''See also:'''
'''See also:'''
[[getPosASLW]], [[setPosASLW]]
[[getPosASLW]], [[setPosASLW]]


== PositionATL ==
=== PositionATL ===
 
Z is measured from the terrain level which varies across the map.
Z is measured from the terrain level which varies across the map.


Line 51: Line 85:
[[getPosATL]], [[setPosATL]], [[getPosATLVisual]], [[ASLToATL]], [[ATLToASL]]
[[getPosATL]], [[setPosATL]], [[getPosATLVisual]], [[ASLToATL]], [[ATLToASL]]


== PositionAGL ==
=== PositionAGL ===
Z is the same as in [[PositionASLW]] when over sea and is the same as in [[PositionATL]] when over land. Most commands either take or return [[PositionAGL]].
 
Z is the same as in [[Position#PositionASLW|PositionASLW]] when over sea and is the same as in [[Position#PositionATL|PositionATL]] when over land. Most commands either take or return [[Position#PositionAGL|PositionAGL]].


'''See also:'''
'''See also:'''
[[modelToWorld]], [[worldToModel]], [[modelToWorldVisual]], [[worldToModelVisual]], [[positionCameraToWorld]], [[intersect]], [[terrainIntersect]], [[isOnRoad]], [[drawIcon3D]], [[drawLine3D]], [[distance]], [[moveTo]], [[doMove]], [[move]], [[setDestination]], [[buildingPos]], [[screenToWorld]], [[worldToScreen]], [[AGLToASL]], [[ASLToAGL]], [[unitAimPosition]], [[unitAimPositionVisual]]
[[modelToWorld]], [[worldToModel]], [[modelToWorldVisual]], [[worldToModelVisual]], [[positionCameraToWorld]], [[intersect]], [[terrainIntersect]], [[isOnRoad]], [[drawIcon3D]], [[drawLine3D]], [[distance]], [[moveTo]], [[doMove]], [[move]], [[setDestination]], [[buildingPos]], [[screenToWorld]], [[worldToScreen]], [[AGLToASL]], [[ASLToAGL]], [[unitAimPosition]], [[unitAimPositionVisual]]


== PositionAGLS ==
=== PositionAGLS ===
 
Over land, Z is measured as height over terrain level minus the height of surface over terrain level underneath. If such surface exists and is counted in, the resulting Z becomes 0.
Over land, Z is measured as height over terrain level minus the height of surface over terrain level underneath. If such surface exists and is counted in, the resulting Z becomes 0.


[[Image:z.jpg|center|frame|Obtaining Z for a unit standing on a rock]]
[[File:z.jpg|center|frame|Obtaining Z for a unit standing on a rock]]


Over sea it gets even more complicated as instead of [[PositionATL]], [[PositionASLW]] is used minus the offset for the surface height, presumably over waves too, as Z seems static. As there is currently no way to obtain H<sub>surface</sub>, it becomes impossible to convert given [[PositionAGLS]] into other formats, unlike with other position formats.
Over sea it gets even more complicated as instead of [[Position#PositionATL|PositionATL]], [[Position#PositionASLW|PositionASLW]] is used minus the offset for the surface height, presumably over waves too, as Z seems static. As there is currently no way to obtain H<sub>surface</sub>, it becomes impossible to convert given [[Position#PositionAGLS|PositionAGLS]] into other formats, unlike with other position formats.


'''See also:'''
'''See also:'''
[[position]], [[visiblePosition]], [[getPos]], [[getPosVisual]]
[[position]], [[visiblePosition]], [[getPos]], [[getPosVisual]]


=== setPosAGLS ===
==== setPosAGLS ====
The function below will place passed object onto walkable surface, if there is one, otherwise on the ground. If only X and Y of the position are supplied, the object will be placed on surface, if Z is supplied, it will be treated as offset from the surface level.
The function below will place passed object onto walkable surface, if there is one, otherwise on the ground. If only X and Y of the position are supplied, the object will be placed on surface, if Z is supplied, it will be treated as offset from the surface level.


<code>KK_fnc_setPosAGLS = {
<sqf>
[[params]] ["_obj", "_pos", "_offset"];
KK_fnc_setPosAGLS = {
_offset = _pos [[select]] 2;
params ["_obj", "_pos", "_offset"];
[[if]] ([[isNil]] "_offset") [[then]] {_offset = 0};
_offset = _pos select 2;
_pos [[set]] [2, [[worldSize]]];  
if (isNil "_offset") then {_offset = 0};
_obj [[setPosASL]] _pos;
_pos set [2, worldSize];
_pos [[set]] [2, [[vectorMagnitude]] (_pos [[vectorDiff]] [[getPosVisual]] _obj) + _offset];
_obj setPosASL _pos;
_obj [[setPosASL]] _pos;
_pos set [2, vectorMagnitude (_pos vectorDiff getPosVisual _obj) + _offset];
_obj setPosASL _pos;
};
};
</code>
</sqf>
<code>{{cc|This will place the player exactly on top deck of Cargo HQ on Stratis:}}
<sqf>
<nowiki>[</nowiki>[[player]], [2437.18,5693.47,0]] [[call]] KK_fnc_setPosAGLS;<br>
// This will place the player exactly on top deck of Cargo HQ on Stratis:
{{cc|This will place the player 2m above top deck of Cargo HQ on Stratis:}}
[player, [2437.18,5693.47,0]] call KK_fnc_setPosAGLS;
<nowiki>[</nowiki>[[player]], [2437.18,5693.47,2]] [[call]] KK_fnc_setPosAGLS;<br>
{{cc|This will place the player 2m below top deck of Cargo HQ on Stratis:}}
<nowiki>[</nowiki>[[player]], [2437.18,5693.47,-2]] [[call]] KK_fnc_setPosAGLS;</code>


Alternatively, [[setVehiclePosition]] can be used. It will put the object onto the nearest surface.
// This will place the player 2m above top deck of Cargo HQ on Stratis:
<code>{{cc|This will place the player inside Cargo HQ on Stratis:}}
[player, [2437.18,5693.47,2]] call KK_fnc_setPosAGLS;
[[player]] [[setVehiclePosition]] [<nowiki/>[2437.18,5693.47,0], [], 0, "CAN_COLLIDE"];<br>
{{cc|This will place the player on top deck of Cargo HQ on Stratis:}}
[[player]] [[setVehiclePosition]] [<nowiki/>[2437.18,5693.47,100], [], 0, "CAN_COLLIDE"];</code>


== PositionWorld ==
// This will place the player 2m below top deck of Cargo HQ on Stratis:
Similar to [[PositionASL]], however Z is measured from the sea level to the the model centre <tt>[0, 0, 0]</tt> of the object, rather than transformed [[boundingCenter]] or land contact vertices.
[player, [2437.18,5693.47,-2]] call KK_fnc_setPosAGLS;
<code>_identical = [[getPosWorld]] _obj [[isEqualTo]] [[AGLtoASL]] (_obj [[modelToWorld]] [0,0,0]); {{cc|should be true}}</code>
</sqf>
 
Alternatively, [[setVehiclePosition]] can be used. It will put the object onto the nearest surface.
<sqf>
// This will place the player inside Cargo HQ on Stratis:
player setVehiclePosition [[2437.18,5693.47,0], [], 0, "CAN_COLLIDE"];
 
// This will place the player on top deck of Cargo HQ on Stratis:
player setVehiclePosition [[2437.18,5693.47,100], [], 0, "CAN_COLLIDE"];
</sqf>
 
=== PositionWorld ===
 
Similar to [[Position#PositionASL|PositionASL]], however Z is measured from the sea level to the the model centre {{hl|[0, 0, 0]}} of the object, rather than transformed [[boundingCenter]] or land contact vertices.
<sqf>_identical = getPosWorld _obj isEqualTo AGLToASL (_obj modelToWorld [0,0,0]); // should be true</sqf>


'''See also:'''
'''See also:'''
[[getPosWorld]], [[setPosWorld]], [[mapCenterOnCamera]]
[[getPosWorld]], [[setPosWorld]], [[mapCenterOnCamera]]


== PositionRelative ==
=== PositionRelative ===
Relative position is normally an <tt>[X, Y, Z]</tt> offset from the model centre.
 
Relative position is normally an {{hl|[X, Y, Z]}} offset from the model centre.


'''See also:'''
'''See also:'''
[[positionCameraToWorld]], [[selectionPosition]], [[attachTo]], [[modelToWorld]], [[worldToModel]], [[modelToWorldVisual]], [[worldToModelVisual]], [[camPrepareRelPos]], [[camSetRelPos]]
[[getRelPos]], [[positionCameraToWorld]], [[selectionPosition]], [[attachTo]], [[modelToWorld]], [[worldToModel]], [[modelToWorldVisual]], [[worldToModelVisual]], [[camPrepareRelPos]], [[camSetRelPos]]
 
=== PositionConfig ===
 
The format used in configs, such as ''mission.sqm'', is {{hl|[X, Z, Y]}}, where Z and Y are swapped around. One other command that uses this format is [[positionCameraToWorld]]. Z in configs is measured from the sea level.


== PositionConfig ==
The format used in configs, such as ''mission.sqm'', is <tt>[X, Z, Y]</tt>, where Z and Y are swapped around. One other command that uses this format is [[positionCameraToWorld]]. Z in configs is measured from the sea level.


[[Category:Arrays]]
[[Category:Arrays]]

Latest revision as of 21:46, 16 May 2024

Positions in Arma games are always represented as arrays. There are two types of positions:

  • 2D position: [X, Y]
  • 3D position: [X, Y, Z]

On the map and on the terrain, the X-axis runs from west to east and the Y-axis runs from south to north. The origin [0, 0] is (usually) located in the bottom left corner.
While the Z-coordinate is always the height/altitude, the point relative to which that height is measured depends on the specific position format (see Types below).

Arma 3
Since Arma 3 v1.94: X, Y and Z are limited to values between -50km and +500km. Using any setPos* command with values greater than that will clamp the value to within these boundaries, not throwing any errors. e.g:
player setPosASL [-50001, 500001, 500001]; // player will be set to [-50000, 500000, 500000]


Commands

See:


Types

A comparison of most common formats, where each curve shows the reference height (Z = 0) for that format. Notice that the ASL format is absolute, i.e. its reference height doesn't change from one place to another, unlike other formats. For example, an object on a mountain and an object at the bottom of the sea both have an ATL height equal to 0.

There are a number of formats available in Real Virtuality:

ASL: Presumably "Above Sea Level"
ATL: Presumably "Above Terrain Level"
ASLW: Presumably "Above Sea Level including Waves"
AGL: Presumably "Above Generic/Ground Level"
AGLS: Presumably "Above Generic/Ground Level including Surfaces"
World: Raw world coordinate system
Relative: Position relative to an object within its model space
Config: Position used in configs
Object: When object is used for position, PositionWorld of the object is used
Visual: Used for rendering objects on the screen. Useful for per-frame applications, such as drawIcon3D - see Command Group: Render Time Scope and Simulation vs Render Time Scope.


Note that the only absolute position format in Arma for 3D calculations is the ASL format. Always pay attention to this fact when performing 3D calculations. For example, when a unit is climbing a mountain, the Z in ATL format is always 0. The following example demonstrates this behavior:

Let's say it is desired to see if there is an intersection between two horizontal positions:

private _pos1 = getPosATL _unit; private _pos2 = _pos1 vectorAdd [0,200,0]; // make a horizontal line by shifting the y, so z remains the same private _intersects = lineIntersects [ATLToASL _pos1, ATLToASL _pos2]; // lineIntersects needs ASL, so we just convert _pos1 and _pos2 to ASL...
However, this is incorrect. ATL is a relative format, and while the ATL height between the coordinates is the same, the ASL height might not be (think of the mountain example again).
This is the correct way to write the above code:

private _pos1 = getPosASL _unit; private _pos2 = _pos1 vectorAdd [0,200,0]; // make a horizontal line by shifting the y private _intersects = lineIntersects [_pos1, _pos2];

Position2D

This array only has two elements and is usually used with 2D information, for example standard markers or UI commands. If used with e.g distance, Z is assumed to be 0.

PositionASL

Z is measured from the sea level which is constant across the map.

See also: getPosASL, setPosASL, getPosASLVisual, visiblePositionASL, ASLToATL, ATLToASL, AGLToASL, ASLToAGL, eyePos, aimPos, getTerrainHeightASL, lineIntersects, lineIntersectsWith, lineIntersectsObjs, lineIntersectsSurfaces, terrainIntersectASL, playSound3D, setDefaultCamera

PositionASLW

Z is measured from the surface of water at that position. Both waves and pond objects affect the result.

See also: getPosASLW, setPosASLW

PositionATL

Z is measured from the terrain level which varies across the map.

See also: getPosATL, setPosATL, getPosATLVisual, ASLToATL, ATLToASL

PositionAGL

Z is the same as in PositionASLW when over sea and is the same as in PositionATL when over land. Most commands either take or return PositionAGL.

See also: modelToWorld, worldToModel, modelToWorldVisual, worldToModelVisual, positionCameraToWorld, intersect, terrainIntersect, isOnRoad, drawIcon3D, drawLine3D, distance, moveTo, doMove, move, setDestination, buildingPos, screenToWorld, worldToScreen, AGLToASL, ASLToAGL, unitAimPosition, unitAimPositionVisual

PositionAGLS

Over land, Z is measured as height over terrain level minus the height of surface over terrain level underneath. If such surface exists and is counted in, the resulting Z becomes 0.

Obtaining Z for a unit standing on a rock

Over sea it gets even more complicated as instead of PositionATL, PositionASLW is used minus the offset for the surface height, presumably over waves too, as Z seems static. As there is currently no way to obtain Hsurface, it becomes impossible to convert given PositionAGLS into other formats, unlike with other position formats.

See also: position, visiblePosition, getPos, getPosVisual

setPosAGLS

The function below will place passed object onto walkable surface, if there is one, otherwise on the ground. If only X and Y of the position are supplied, the object will be placed on surface, if Z is supplied, it will be treated as offset from the surface level.

KK_fnc_setPosAGLS = { params ["_obj", "_pos", "_offset"]; _offset = _pos select 2; if (isNil "_offset") then {_offset = 0}; _pos set [2, worldSize]; _obj setPosASL _pos; _pos set [2, vectorMagnitude (_pos vectorDiff getPosVisual _obj) + _offset]; _obj setPosASL _pos; };
// This will place the player exactly on top deck of Cargo HQ on Stratis: [player, [2437.18,5693.47,0]] call KK_fnc_setPosAGLS; // This will place the player 2m above top deck of Cargo HQ on Stratis: [player, [2437.18,5693.47,2]] call KK_fnc_setPosAGLS; // This will place the player 2m below top deck of Cargo HQ on Stratis: [player, [2437.18,5693.47,-2]] call KK_fnc_setPosAGLS;

Alternatively, setVehiclePosition can be used. It will put the object onto the nearest surface.

// This will place the player inside Cargo HQ on Stratis: player setVehiclePosition [[2437.18,5693.47,0], [], 0, "CAN_COLLIDE"]; // This will place the player on top deck of Cargo HQ on Stratis: player setVehiclePosition [[2437.18,5693.47,100], [], 0, "CAN_COLLIDE"];

PositionWorld

Similar to PositionASL, however Z is measured from the sea level to the the model centre [0, 0, 0] of the object, rather than transformed boundingCenter or land contact vertices.

_identical = getPosWorld _obj isEqualTo AGLToASL (_obj modelToWorld [0,0,0]); // should be true

See also: getPosWorld, setPosWorld, mapCenterOnCamera

PositionRelative

Relative position is normally an [X, Y, Z] offset from the model centre.

See also: getRelPos, positionCameraToWorld, selectionPosition, attachTo, modelToWorld, worldToModel, modelToWorldVisual, worldToModelVisual, camPrepareRelPos, camSetRelPos

PositionConfig

The format used in configs, such as mission.sqm, is [X, Z, Y], where Z and Y are swapped around. One other command that uses this format is positionCameraToWorld. Z in configs is measured from the sea level.