Вектор (Vector)

From Valve Developer Community
< Ru
Jump to navigation Jump to search
English (en)Deutsch (de)Français (fr)Русский (ru)Translate (Translate)

Vector это C++ класс, который представляет направление и длину отрезка прямой, начинающегося в точке отсчёта (origin)(en).

Оси

Каждый вектор содержит три vec_t(en) координаты:

X
+вперёд/-назад
Y
+влево/-вправо
Z
+вверх/-вниз

(1,20,5) означает 1 единица(en) вперёд, 20 единиц влево и 5 единиц вверх.

{{Note|Класс вектора в Source является геометрическим понятием и сильно отличается от вектора (C++) из стандартной библиотеки STL, который является Ru:Массив (тип данных)|массивом. Вектор из STL в Source переименован в CUtlVector(en).]]

Объявление

 Vector vecMyVector = Vector(1,20,5); 
  • Класс вектора пишется как Vector, а не vector.
  • Вы можете определять значения X, Y и Z отдельно.
  • Префикс vec (или просто v) определяет переменную как вектор.

Направление

У вектора нет явно указанного направления, оно определяется кодом, который его использует.

В подавляющем большинстве случаев вектор рассчитывается относительно координат мира независимо от вращения объекта, но есть несколько случаев (например, при применении физических сил), которые рассчитываются относительно координат объекта.

Невозможно определить, какая интерпретация будет использоваться для переменной, поэтому изучайте описание используемых функций. Используйте VectorRotate() и VectorIRotate() для преобразования между системами отсчёта.

Использование

Позиционирование
Местоположение каждого объекта 'точка отсчёта (origin)' хранится в виде вектора относительно его родительского(en) объекта в системе декартовых координат(en). Более подробную информацию смотрите в описании функции GetAbsOrigin()(en).
Движение
Объекты перемещаются на расстояние равное вектору скорости(en) один раз в секунду.
Траектории столкновений
Траектория полета(en) рассчитывается из одной точки в другую, определяя, во что она "попадает" на своем пути с учётом ограничивающего короба (-hull)(en).

Операции

Чтобы результат имел смысл, все векторы в операции должны иметь общую точку отсчёта(en). Используется ли локальное или абсолютное начало отсчёта, зависит от того, чего вы пытаетесь достичь.

Сложение

Сложение двух (или более) векторов складывает их значения. Вы уже складывали векторы, если толкали что либо двумя руками!

Сложение векторов: (4,1) + (-3,1) = (1,2)

Вычитание

Вычитание одного вектора из другого это разница между ними - другими словами, как добраться из первого вектора в другой.

Вычитание векторов: (2,3) - (-2,1) = (4,2)
Tip.pngСовет: От порядка векторов зависит направление получившегося вектора

Умножение(произведение)

Скалярное

Умножение или деление вектора скалярно (то есть на целое(en) или вещественное(en) число) изменит длину вектора не изменяя его направления.

Скалярное произведение векторов: (1,2) x 2 = (2,4)
Tip.pngСовет: Делениние вектора на его длину нормирует(en) его. Используйте VectorNormalize() чтобы быстро это сделать.

Нормированное скалярное

Умножение двух векторов с последующем сложением ординат результата даёт скалярное произведение, которое после нормирования(en) обоих векторов, равно косинусу угла между ними.

Одно из применений скалярного произведения - это определение того, насколько совпадают два вектора. +1 означает совпадение, 0 означает, что они перпендикулярны друг другу, а -1 означает, что они противоположны.

Note.pngПримечание: Точное скалярное произведение получается только если длина обоих векторов равна 1. В следующем примере шаг нормирования(en) пропущен для упрощения (при этом положительное/нулевое/отрицательное соотношения по-прежнему выполняется).
Принцип вычисления нормированного скалярное произведения: (2,2) x (-2,0) = (-4,0) = -4; (2,2) x (-2,2) = (-4,4) = 0; (2,2) x (2,2) = (4,4) = 8

Этот код вычисляет скалярное произведение с помощью различных вспомогательных функций Source:

Vector vecTarget = pTarget->GetAbsOrigin() - GetAbsOrigin();	// Вычисление относительного вектора к цели
VectorNormalize(vecTarget);	// Предварительно должно быть выполнено номирование

Vector vecFacing;
AngleVectors(GetLocalAngles(), &vecFacing);	// Преобразование угла поворота в эквивалентный вектор (нормированный)

float result = DotProduct(vecTarget, vecFacing);	// Вычисление скалярного произведения

if (result > 0)
	Msg("Цель прямо передо мной!\n");
Tip.pngСовет: Нет необходимости нормировать, если проверяется только местоположение друг напротив друга.

В этом коде выражение result > 0 истинно, если угол между входными векторами < 90°. Если нужно, чтобы два вектора находились под углом < α градусов друг к другу, то значение result > cos(α°) должно быть истинным, где cos(α°) - константа. Обратите внимание, что таким образом, скалярное произведение позволяет проверить угол между двумя векторами без вызова довольно дорогостоящей функции косинуса во время выполнения.

Icon-Important.pngВажно: Существуют различные объекты, ключ-параметры которых обозначают максимальный угол, который указывается вещественным числом в диапазоне от -1.0 до 1.0, например, ключ-параметр FieldOfView объекта trigger_look. Такие ключ-параметры обычно относятся к скалярному произведению, которое не является линейной функцией желаемого угла. Распространенной ошибкой является установка значения 0.5, которое якобы соответствует углу в 45°, тогда как правильным значением будет cos(45°) ≈ 0.707!
Угол между векторами α° cos-1(значение) 10° 15° 30° 45° 60° 75° 90° 120° 180°
Нормированное скалярное произведение cos(α°) значение 1.0 0.99985 0.99939 0.99619 0.98481 0.96593 0.86603 0.70711 0.5 0.25882 0 -0.5 -1.0

Векторное

Векторное произведение - это вектор, перпендикулярный двум входным векторам. Оно используется для экстраполяции третьего измерения: векторное произведение векторов, направленного вдоль оси X, и вектора, направленного вдоль оси Y, даёт вектор, направленным вдоль оси Z.

Уравнение сложное, но его не нужно заучивать; просто используйте функцию CrossProduct(vecA, vecB, &vecResult). Как правило, нет необходимости нормировать входные векторы. Большинство разработчиков редко будут использовать векторное произведение, если вообще будут, но при необходимости имейте в виду, что для правильного понимания этой операции требуется умеренное количество математических вычислений.

Поворот

Для поворота вектора нужна матрица(en), это нельзя сделать также легко как умножение. К счастью не нужно в это вникать: можно просто вызвать VectorRotate(Vector in, QAngle in, Vector& out).

Специальные вектора

В Source есть два вида специальных векторов:

vec3_origin
Vector(0,0,0).
vec3_invalid
Это используется для недопустимых векторов, например, если результатом функцим станет вектор к точке на пересечении двух параллельных прямых.

Функции пользователя

Длина

vec_t(en) Length()
vec_t LengthSqr()
Length() возвращает длину вектора в единицах измерения(en). Быстрее использовать функцию LengthSqr() и возводить в квадрат другое сравниваемое значение.
bool(en) IsLengthGreaterThan(flValue)
bool IsLengthLessThan(flValue)
Функции быстрой проверки длины с использованием LengthSqr().
void Zero()
Устанавливает все ординаты в 0.

Направление

void Init(vec_t X, Y, Z)
Задаёт ординаты существующего вектора.
void Random(vec_t minVal, vec_t maxVal)
Выполняет случайный выбор всех трёх ординат в указанном диапазоне значений.
void Negate()
Меняет ординаты на соотвествующие противоположному направлению вектора, не изменяя его длину.
Vector Max(vOther)
Vector Min(vOther)
Усекает ординаты вектора либо выше, либо ниже заданных значений. Ординаты изменяются независимо, без сохранения пропорций (т.е. направление может измениться).

Сравнение

vec_t DistTo(vOther)
vec_t DistToSqr(vOther)
Возвращает расстояние между текущим и указанным вектором vOther как скалярную величину. Обычно, преобразование в квадрат работает быстрее.
vec_t Dot(vOther)
Возвращает нормированное скалярное произведение текущего и указанного вектора vOther.
Vector Cross(vOther)
Возвращает векторное произведение текущего и указанного вектора vOther.
bool WithinAABox(vecBoxmin,vecBoxmax)
Проверяет, заканчивается ли вектор в пределах заданной прямоугольной области. Минимальные и максимальные точки области рассчитываются относительно вектора.

Приведение

Vector2D AsVector2D()
Выполняет приведение вектора к Vector2D(en).
vec_t Length2D()
vec_t Length2DSqr()
As their standard equivalents, but ignoring the Z-axis.
Base()
Casts to vec_t(en)*, basically the same as &vec.x or (float*)&vec.

Вспомогательные функции

Все эти глобальные функции доступны в файле cbase.h.

float(en) VectorNormalize(vec)
Делит вектор на его длину, нормирует(en) его. Умножает вектор и возвращает его изначальную длину.
vec_t(en) DotProduct(vecA, vecB)
Смотрите Нормированное скалярное произведение.
void CrossProduct(vecA,vecB,vecResult)
Смотрите Векторное произведение.
void VectorTransform(Vector in1, matrix3x4_t in2, Vector out)
Смотрите matrix3x4_t(en).

Смотреть также