Difference between revisions of "Vector"

From Valve Developer Community
Jump to: navigation, search
(Orientation: simplified)
m (linked the german translation)
 
(27 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 +
{{otherlang2
 +
|title=<code>Vector</code>
 +
|fr=Vector:fr
 +
|de=Vector:de
 +
}}
 +
 
{{toc-right}}
 
{{toc-right}}
  
'''Vector''' is a C++ class that represents a line with direction and length, starting at the current [[origin]].
+
'''<code>Vector</code>''' is a C++ class that represents a line with direction and length, starting at the current [[origin]]. Each vector contains three <code>[[vec_t]]</code> ordinates:
  
Each vector contains three <code>[[vec_t]]</code> 'ordinates'. <code>(0,20,5)</code> means 20 [[unit]]s in front of and 5 units above the current origin.
+
* '''X''' +forward/-backward
 +
* '''Y''' +left/-right
 +
* '''Z''' +up/-down
 +
 
 +
<code>(1,20,5)</code> means 1 [[unit]] forward, 20 units to the left and 5 units above the current origin.
  
 
{{note|Source's vector class is geometric and ''very'' different from [[Wikipedia:Vector (C++)|the Standard Template Library's]], which is a type of [[Wikipedia:Array|array]]. The STL-style vector has been renamed <code>[[CUtlVector]]</code> in Source.}}
 
{{note|Source's vector class is geometric and ''very'' different from [[Wikipedia:Vector (C++)|the Standard Template Library's]], which is a type of [[Wikipedia:Array|array]]. The STL-style vector has been renamed <code>[[CUtlVector]]</code> in Source.}}
Line 9: Line 19:
 
== Declaration ==
 
== Declaration ==
  
  Vector vecMyVector = Vector(0,20,5);
+
  Vector vecMyVector = Vector(1,20,5);
  
 
* The classname <code>Vector</code> is case-sensitive.
 
* The classname <code>Vector</code> is case-sensitive.
* You could also assign to the X, Y and Z member variables separately.
+
* You can construct it by defining the X, Y and Z member variables separately, pass a single value for all three or copying the data of another Vector.
* <code>vec</code> (or sometimes just <code>v</code>) identifies the variable as a <code>Vector</code>.
+
* The prefix <code>vec</code> (or sometimes just <code>v</code>) identifies the variable as a vector.
  
 
== Orientation ==
 
== Orientation ==
Line 19: Line 29:
 
A vector does not have an orientation; that is determined by the code that uses it.
 
A vector does not have an orientation; that is determined by the code that uses it.
  
In the vast majority of cases a vector will be interpreted as '''world axis aligned''' regardless of an entity's rotation, but there are few cases(e.g. applying physics forces), where they are instead '''object axis aligned'''.
+
In the vast majority of cases a vector will be interpreted as '''world axis aligned''' regardless of an entity's rotation, but there are few cases (e.g. applying physics forces), where they are considered '''object axis aligned'''.
  
There is no way of telling which interpretation will be used from the variable, so check for function comments when in doubt. Use <code>VectorRotate()</code> and <code>VectorIRotate()</code> to translate between alignments.
+
There is no way of telling which interpretation will be used from the variable, so check for function comments when in doubt. Use [[#Helper functions|<code>VectorRotate()</code>]] and [[#Helper functions|<code>VectorIRotate()</code>]] to translate between alignments.
  
 
== Uses ==
 
== Uses ==
  
=== Positioning ===
+
; Positioning
 
+
: Every entity's position ('origin') is stored as a vector relative to its [[parent]]: you are likely to be familiar with this idea already as [[coordinates|Cartesian grid coordinates]]. See <code>[[GetAbsOrigin()]]</code> for more details.
Every entity's position is stored as a vector relative to its [[parent]]. You are likely to be familiar with this idea already as Cartesian [[coordinates|grid coordinates]].
+
; Movement
 
+
: An entity attempts to move the length of its [[velocity]] vector once per second.
The parent-relative vector stored by the entity is 'local'; calculating an 'absolute' vector relative to the [[world]] requires extra work. The two Abs functions below do that work for you, but are more [[expensive]].
+
; Collision Traces
 
+
: A [[UTIL_TraceLine|Traceline]] or [[UTIL_TraceHull|-hull]] is fired from one point to another, detecting what it "hits" along its path.
* <code>[[GetAbsOrigin()]]</code>, <code>[[SetAbsOrigin()]]</code>
 
* <code>[[GetLocalOrigin()]]</code>, <code>[[SetLocalOrigin()]]</code>
 
 
 
=== Movement ===
 
 
 
An entity attempts to move the length of its velocity vector once per second. The code looks something like this:
 
 
 
Vector velocity = Vector(0,5,0); ''// 5 units/second in the +Y direction''
 
 
Vector vecNewOrigin = GetAbsOrigin() + velocity * [[gpGlobals]]->frametime; ''// frametime is in seconds, e.g. 0.033''
 
 
SetAbsOrigin(vecNewOrigin);
 
 
 
Notice how <code>frametime</code> is used to regulate the entity's speed regardless of how long each frame takes to calculate. See [[#Scalar|scalar multiplication]] for more detail on the operation.
 
 
 
As with the origin, velocity is stored relative to the parent. AbsVelocity represents the velocity relative to the rest frame of the world, and is the more commonly used method.
 
 
 
* <code>[[GetAbsVelocity()]]</code>, <code>[[SetAbsVelocity()]]</code>
 
* <code>[[GetLocalVelocity()]]</code>, <code>[[SetLocalVelocity()]]</code>
 
 
 
=== Tracelines ===
 
 
 
''Main article: [[TraceLines]]''
 
 
 
Tracing is the process of going from a point A towards another point B, and finding out the first thing that we "hit" on our way from A to B ('''TraceLine''').
 
  
 
== Operations ==
 
== Operations ==
Line 65: Line 50:
 
Adding two (or more) vectors '''combines''' them. You have already experienced vector addition if you've ever pushed an object with two hands!
 
Adding two (or more) vectors '''combines''' them. You have already experienced vector addition if you've ever pushed an object with two hands!
  
[[Image:Vector_add.png|center|Vector addition: (4,1) + (-3,1) = (1,2)]]
+
[[File:Vector_add.png|center|Vector addition: (4,1) + (-3,1) = (1,2)]]
  
 
=== Subtraction ===
 
=== Subtraction ===
Line 71: Line 56:
 
Subtracting one vector from another produces the '''difference''' between the two - in other words, how to get to the first location from the second. The result is local to the ''second'' vector.
 
Subtracting one vector from another produces the '''difference''' between the two - in other words, how to get to the first location from the second. The result is local to the ''second'' vector.
  
[[Image:Vector_subtraction.png|center|Vector subtraction: (2,3) - (-2,1) = (4,2)]]
+
[[File:Vector_subtraction.png|center|Vector subtraction: (2,3) - (-2,1) = (4,2)]]
  
 
{{tip|The order in which you subtract defines the direction of the vector.}}
 
{{tip|The order in which you subtract defines the direction of the vector.}}
Line 81: Line 66:
 
Multiplying or dividing a vector by a [[Wikipedia:Scalar|scalar]] (i.e. an [[int]] or [[float]]) will change its '''length''' (sometimes called "magnitude") without affecting its direction.
 
Multiplying or dividing a vector by a [[Wikipedia:Scalar|scalar]] (i.e. an [[int]] or [[float]]) will change its '''length''' (sometimes called "magnitude") without affecting its direction.
  
[[Image:Vector-scalar_multiply.png|center|Vector-scalar multiplication: (1,2) x 2 = (2,4)]]
+
[[File:Vector-scalar_multiply.png|center|Vector-scalar multiplication: (1,2) x 2 = (2,4)]]
  
 
{{tip|Dividing a vector by its length [[normal]]ises it. Use <code>VectorNormalize()</code> to do this quickly.}}
 
{{tip|Dividing a vector by its length [[normal]]ises it. Use <code>VectorNormalize()</code> to do this quickly.}}
Line 87: Line 72:
 
==== Dot product ====
 
==== Dot product ====
  
Multiplying two vectors then adding the result's ordinates produces a dot product, which when both vectors have been normalised (see above) is equal to the '''cosine''' of the angle between the two vectors.
+
Multiplying two vectors then adding the result's ordinates produces a dot product, which when both vectors have been [[normal]]ised is equal to the '''cosine''' of the angle between the two vectors.
  
 
One use of a dot product is to tell how closely the two vectors align. +1 means a match, 0 means they are perpendicular to each other, and -1 means they are opposed.
 
One use of a dot product is to tell how closely the two vectors align. +1 means a match, 0 means they are perpendicular to each other, and -1 means they are opposed.
Line 93: Line 78:
 
{{note|''True dot products are only produced when the length of both vectors is 1.'' The [[normal]]isation step has been skipped in the following demonstration to make its equations simpler (but the positive/zero/negative rule still applies).}}
 
{{note|''True dot products are only produced when the length of both vectors is 1.'' The [[normal]]isation step has been skipped in the following demonstration to make its equations simpler (but the positive/zero/negative rule still applies).}}
  
[[Image:Vector_dotproduct.png|center|Vector dot products: (2,2) x (-2,0) = (-4,0) = -4; (2,2) x (-2,2) = (-4,4) = 0; (2,2) x (2,2) = (4,4) = 8]]
+
[[File:Vector_dotproduct.png|center|Vector dot products: (2,2) x (-2,0) = (-4,0) = -4; (2,2) x (-2,2) = (-4,4) = 0; (2,2) x (2,2) = (4,4) = 8]]
  
 
This code calculates a dot product with the aid of Source's various helper functions:
 
This code calculates a dot product with the aid of Source's various helper functions:
  
Vector vecTarget = GetAbsOrigin() - pTarget->GetAbsOrigin(); ''// Get local vector to target''
+
<source lang=cpp>
'''VectorNormalize'''(vecTarget); ''// Normalisation needs to be done beforehand''
+
Vector vecTarget = pTarget->GetAbsOrigin() - GetAbsOrigin(); // Get local vector to target
+
VectorNormalize(vecTarget); // Normalisation needs to be done beforehand
Vector vecFacing;
+
 
'''[[AngleVectors()|AngleVectors]]'''(GetLocalAngles(),&vecFacing); ''// Convert facing angle to equivalent vector (arrives normalised)''
+
Vector vecFacing;
+
AngleVectors(GetLocalAngles(),&vecFacing); // Convert facing angle to equivalent vector (arrives normalised)
float result = '''DotProduct'''(vecTarget,vecFacing); ''// Get the dot product.''
+
 
+
float result = DotProduct(vecTarget,vecFacing); // Get the dot product
if (result > 0)
+
 
Msg("pTarget is in front of me!\n");
+
if (result > 0)
 +
Msg("pTarget is in front of me!\n");
 +
</source>
  
 
{{tip|There is no need to normalise if you only care about whether one location is in front of another.}}
 
{{tip|There is no need to normalise if you only care about whether one location is in front of another.}}
Line 114: Line 101:
 
A cross product is a vector '''perpendicular''' to two input vectors. It's used to extrapolate a third dimension from just two: the cross product of a vector pointing down the X-axis and a vector pointing down the Y-axis is a vector pointing down the Z-axis.
 
A cross product is a vector '''perpendicular''' to two input vectors. It's used to extrapolate a third dimension from just two: the cross product of a vector pointing down the X-axis and a vector pointing down the Y-axis is a vector pointing down the Z-axis.
  
The equation is fiddly and doesn't have to be learnt; just use <code>CrossProduct(vecA,vecB,&vecResult)</code>. There generally isn't any need to normalise the input vectors. Most modders will likely only use cross products rarely, if ever - but if required, be aware that a [http://mathworld.wolfram.com/CrossProduct.html moderate amount of math] is required to [http://en.wikipedia.org/wiki/Cross_product properly understand] this operation.
+
The equation is fiddly and doesn't have to be learnt; just use <code>CrossProduct(vecA,vecB,&vecResult)</code>. There generally isn't any need to normalise the input vectors. Most modders will likely only use cross products rarely, if ever - but if required, be aware that a [http://mathworld.wolfram.com/CrossProduct.html moderate amount of math] is required to [[Wikipedia:Cross product|properly understand]] this operation.
 +
 
 +
== Rotation ==
 +
 
 +
Rotating a Vector requires a [[matrix3x4_t|matrix]], so can't be done with an operation like those above. Thankfully you don't need to get involved in the gritty details: just call <code>VectorRotate(Vector in, QAngle in, Vector& out)</code>.
 +
 
 +
== Special Vectors ==
 +
 
 +
Source defines two special Vectors:
 +
 
 +
; <code>vec3_origin</code>
 +
: Vector(0,0,0).
 +
; <code>vec3_invalid</code>
 +
: This is used for invalid Vectors, e.g. if you need to return a Vector in a function, but something is not possible (such as the intersection-point of two parallel straight lines).
  
 
== Member functions ==
 
== Member functions ==
Line 121: Line 121:
 
; <code>[[vec_t]] Length()</code>
 
; <code>[[vec_t]] Length()</code>
 
; <code>vec_t LengthSqr()</code>
 
; <code>vec_t LengthSqr()</code>
: <code>Length()</code> returns the vector's length in [[unit]]s. It's faster to use <code>LengthSqr()</code> and square the value for comparison, however.
+
: <code>Length()</code> returns the vector's length in [[unit]]s. It's faster to use <code>LengthSqr()</code> and square the other value being compared.
 
; <code>[[bool]] IsLengthGreaterThan(flValue)</code>
 
; <code>[[bool]] IsLengthGreaterThan(flValue)</code>
 
; <code>bool IsLengthLessThan(flValue)</code>
 
; <code>bool IsLengthLessThan(flValue)</code>
 
: Helpers that perform fast length checks using <code>LengthSqr()</code>.
 
: Helpers that perform fast length checks using <code>LengthSqr()</code>.
 
; <code>void Zero()</code>
 
; <code>void Zero()</code>
: Guess what?
+
: Sets all elements to 0.
  
 
=== Direction ===
 
=== Direction ===
Line 150: Line 150:
 
: Returns the [[#Cross product|cross product]] of the current vector and <code>vOther</code>.
 
: Returns the [[#Cross product|cross product]] of the current vector and <code>vOther</code>.
 
; <code>bool WithinAABox(vecBoxmin,vecBoxmax)</code>
 
; <code>bool WithinAABox(vecBoxmin,vecBoxmax)</code>
: Does the vector end within this box? Argument vectors are local.
+
: Tests whether the Vector ends within the given box. Box min/max values are local to the Vector.
  
 
=== Casts ===
 
=== Casts ===
Line 160: Line 160:
 
: As their standard equivalents, but ignoring the Z-axis.
 
: As their standard equivalents, but ignoring the Z-axis.
 
; <code>Base()</code>
 
; <code>Base()</code>
: Casts to [[vec_t]]. {{todo|What does that achieve?}}
+
: Casts to [[vec_t]]*, basically the same as &vec.x or (float*)&vec.
  
 
== Helper functions ==
 
== Helper functions ==
  
; <code>vec_t DotProduct(vecA,vecB)</code>
+
These globals are all available through <code>cbase.h</code>.
 +
 
 +
; <code>[[float]] VectorNormalize(vec)</code>
 +
: Divides the vector by its length, [[normal]]ising it. Modifies the Vector and returns the old length.
 +
; <code>[[vec_t]] DotProduct(vecA,vecB)</code>
 
: See [[#Dot product]].
 
: See [[#Dot product]].
; <code>void CrossProduct(const Vector& a, const Vector& b, Vector& result )</code>
+
; <code>void CrossProduct(vecA,vecB,vecResult)</code>
 
: See [[#Cross product]].
 
: See [[#Cross product]].
 
+
; <code>void VectorTransform(Vector in1, matrix3x4_t in2, Vector out)</code>
* <code>[[UTIL_VecToYaw()]]</code>, <code>[[UTIL_VecToPitch()]]</code>
+
: See [[matrix3x4_t]].
* <code>[[AngleVectors()]]</code> and <code>[[VectorAngles()]]</code>
+
* [[UTIL_VecToYaw()|<code>UTIL_VecToYaw()</code> / <code>UTIL_VecToPitch()</code>]]
* <code>[[VectorNormalize()]]</code>
+
* [[AngleVectors()|<code>AngleVectors()</code> / <code>VectorAngles()</code>]]
  
 
== See also ==
 
== See also ==
Line 177: Line 181:
 
* [[Wikipedia:Euclidean vector]]
 
* [[Wikipedia:Euclidean vector]]
 
* <code>[[vec_t]]</code>
 
* <code>[[vec_t]]</code>
* <code>[[VectorVectors]]</code>
 
 
* <code>[[Vector2D]]</code>
 
* <code>[[Vector2D]]</code>
 
* <code>[[QAngle]]</code>
 
* <code>[[QAngle]]</code>
 +
* <code>[[matrix3x4_t]]</code>
 
* <code>[[CUtlVector]]</code>
 
* <code>[[CUtlVector]]</code>
  

Latest revision as of 23:18, 25 April 2013

Deutsch Français

Vector is a C++ class that represents a line with direction and length, starting at the current origin. Each vector contains three vec_t ordinates:

  • X +forward/-backward
  • Y +left/-right
  • Z +up/-down

(1,20,5) means 1 unit forward, 20 units to the left and 5 units above the current origin.

Note:Source's vector class is geometric and very different from the Standard Template Library's, which is a type of array. The STL-style vector has been renamed CUtlVector in Source.

Declaration

Vector vecMyVector = Vector(1,20,5);
  • The classname Vector is case-sensitive.
  • You can construct it by defining the X, Y and Z member variables separately, pass a single value for all three or copying the data of another Vector.
  • The prefix vec (or sometimes just v) identifies the variable as a vector.

Orientation

A vector does not have an orientation; that is determined by the code that uses it.

In the vast majority of cases a vector will be interpreted as world axis aligned regardless of an entity's rotation, but there are few cases (e.g. applying physics forces), where they are considered object axis aligned.

There is no way of telling which interpretation will be used from the variable, so check for function comments when in doubt. Use VectorRotate() and VectorIRotate() to translate between alignments.

Uses

Positioning
Every entity's position ('origin') is stored as a vector relative to its parent: you are likely to be familiar with this idea already as Cartesian grid coordinates. See GetAbsOrigin() for more details.
Movement
An entity attempts to move the length of its velocity vector once per second.
Collision Traces
A Traceline or -hull is fired from one point to another, detecting what it "hits" along its path.

Operations

All vectors in an operation must have the same origin for the result to make sense. Whether a local or absolute origin is used depends on what you're trying to achieve.

Addition

Adding two (or more) vectors combines them. You have already experienced vector addition if you've ever pushed an object with two hands!

Vector addition: (4,1) + (-3,1) = (1,2)

Subtraction

Subtracting one vector from another produces the difference between the two - in other words, how to get to the first location from the second. The result is local to the second vector.

Vector subtraction: (2,3) - (-2,1) = (4,2)
Tip:The order in which you subtract defines the direction of the vector.

Multiplication

Scalar

Multiplying or dividing a vector by a scalar (i.e. an int or float) will change its length (sometimes called "magnitude") without affecting its direction.

Vector-scalar multiplication: (1,2) x 2 = (2,4)
Tip:Dividing a vector by its length normalises it. Use VectorNormalize() to do this quickly.

Dot product

Multiplying two vectors then adding the result's ordinates produces a dot product, which when both vectors have been normalised is equal to the cosine of the angle between the two vectors.

One use of a dot product is to tell how closely the two vectors align. +1 means a match, 0 means they are perpendicular to each other, and -1 means they are opposed.

Note:True dot products are only produced when the length of both vectors is 1. The normalisation step has been skipped in the following demonstration to make its equations simpler (but the positive/zero/negative rule still applies).
Vector dot products: (2,2) x (-2,0) = (-4,0) = -4; (2,2) x (-2,2) = (-4,4) = 0; (2,2) x (2,2) = (4,4) = 8

This code calculates a dot product with the aid of Source's various helper functions:

Vector vecTarget = pTarget->GetAbsOrigin() - GetAbsOrigin();	// Get local vector to target
VectorNormalize(vecTarget);	// Normalisation needs to be done beforehand

Vector vecFacing;
AngleVectors(GetLocalAngles(),&vecFacing);	// Convert facing angle to equivalent vector (arrives normalised)

float result = DotProduct(vecTarget,vecFacing);	// Get the dot product

if (result > 0)
	Msg("pTarget is in front of me!\n");
Tip:There is no need to normalise if you only care about whether one location is in front of another.

Cross product

A cross product is a vector perpendicular to two input vectors. It's used to extrapolate a third dimension from just two: the cross product of a vector pointing down the X-axis and a vector pointing down the Y-axis is a vector pointing down the Z-axis.

The equation is fiddly and doesn't have to be learnt; just use CrossProduct(vecA,vecB,&vecResult). There generally isn't any need to normalise the input vectors. Most modders will likely only use cross products rarely, if ever - but if required, be aware that a moderate amount of math is required to properly understand this operation.

Rotation

Rotating a Vector requires a matrix, so can't be done with an operation like those above. Thankfully you don't need to get involved in the gritty details: just call VectorRotate(Vector in, QAngle in, Vector& out).

Special Vectors

Source defines two special Vectors:

vec3_origin
Vector(0,0,0).
vec3_invalid
This is used for invalid Vectors, e.g. if you need to return a Vector in a function, but something is not possible (such as the intersection-point of two parallel straight lines).

Member functions

Length

vec_t Length()
vec_t LengthSqr()
Length() returns the vector's length in units. It's faster to use LengthSqr() and square the other value being compared.
bool IsLengthGreaterThan(flValue)
bool IsLengthLessThan(flValue)
Helpers that perform fast length checks using LengthSqr().
void Zero()
Sets all elements to 0.

Direction

void Init(vec_t X, Y, Z)
Quickly set an existing vector's ordinates.
void Random(vec_t minVal,vec_t maxVal)
Randomises all three ordinates within the given range.
void Negate()
Reverses the vector's direction without affecting its length.
Vector Max(vOther)
Vector Min(vOther)
Clamps the vector's ordinates either above or below the given values. The ordinates won't stay in proportion (i.e. direction might change).

Comparison

vec_t DistTo(vOther)
vec_t DistToSqr(vOther)
Returns the distance between the current vector and vOther as a scalar. As ever, the squared flavour is faster.
vec_t Dot(vOther)
Returns the dot product of the current vector and vOther.
Vector Cross(vOther)
Returns the cross product of the current vector and vOther.
bool WithinAABox(vecBoxmin,vecBoxmax)
Tests whether the Vector ends within the given box. Box min/max values are local to the Vector.

Casts

Vector2D AsVector2D()
Casts to Vector2D.
vec_t Length2D()
vec_t Length2DSqr()
As their standard equivalents, but ignoring the Z-axis.
Base()
Casts to vec_t*, basically the same as &vec.x or (float*)&vec.

Helper functions

These globals are all available through cbase.h.

float VectorNormalize(vec)
Divides the vector by its length, normalising it. Modifies the Vector and returns the old length.
vec_t DotProduct(vecA,vecB)
See #Dot product.
void CrossProduct(vecA,vecB,vecResult)
See #Cross product.
void VectorTransform(Vector in1, matrix3x4_t in2, Vector out)
See matrix3x4_t.

See also