 |
Векторы в трехмерном пространстве
Геометрическим представлением вектора является направленный отрезок прямой линии, что показано на рис. У каждого вектора есть два свойства: длина (также называемая модулем или нормой вектора) и направление. Благодаря этому векторы очень удобны для моделирования физических величин, которые характеризуются модулем и направлением. В трехмерной компьютерной графике векторы часто используются только для моделирования направления. Например, нам часто требуется указать направление распространения световых лучей, ориентацию грани или направление камеры, глядящей на трехмерный мир. Векторы обеспечивают удобный механизм задания направления в трехмерном пространстве.
 | Свободные векторы, определенные независимо от системы координат |
Поскольку местоположение не является характеристикой вектора, два вектора с одинаковой длиной и указывающие в одном и том же направлении считаются равными, даже если они расположены в различных местах. Обратите внимание, что два таких вектора будут параллельны друг другу. Например, на рис. векторы u и v равны.
На рис. видно, что обсуждние векторов может вестись без упоминания системы координат, поскольку всю значимую информацию, — длину и направление, — вектор содержит в себе. Добавление системы координат не добавляет информации в вектор; скорее можно говорить, что вектор, значения которого являются его неотъемлимой частью, просто описан относительно конкретной системы координат. И если мы изменим систему координат, мы только опишем тот же самый вектор относительно другой системы.
Отметив этот важный момент, мы перейдем к изучению того, как векторы описываются в левосторонней трехмерной декартовой системе координат. На рис. показаны левосторонняя и правосторонняя системы координат. Различие между ними — положительное направление оси Z. В левосторонней системе координат положительное направление оси Z погружается в страницу. В правосторонней системе координат положительное направление оси Z направлено от страницы.
 | Слева изображена левосторонняя система координат. Обратите внимание, что положительное направление оси Z направлено вглубь страницы. Справа изображена правостороняя система координат. Здесь положительное направление оси Z направлено от страницы
|
Поскольку местоположение вектора не изменяет его свойств, мы можем перенести векторы таким образом, чтобы начало каждого из них совпадало с началом координат выбранной координатной системы. Когда начало вектора совпадает с началом координат, говорят, что вектор находится в стандартной позиции. Таким образом, если вектор находится в стандартной позиции, мы можем описать его, указав только координаты конечной точки. Мы будем называть эти координаты компонентами вектора. На рис. 3 показаны векторы, изображенные на рис. 1, которые были перемещены в стандартные позиции.
 | Векторы в стандартной позиции, определенные в указанной системе координат. Обратите внимание, что векторы u и v полностью совпадают друг с другом потому что они равны |
ПРИМЕЧАНИЕ
Поскольку мы описываем находящийся в стандартной позиции вектор, указывая его конечную точку, как если бы мы описывали отдельную точку, легко перепутать точку и вектор. Чтобы подчеркнуть различия между этими двумя понятиями, мы вновь приведем определение каждого из них. Точка описывает только местоположение в системе координат, в то время как вектор описывает величину и направление.
Мы будем пользоваться для обозначения векторов полужирными строчными буквами, но иногда будем применять и полужирные заглавные буквы. Вот пример двух-, трех- и четырехмерных векторов соответственно: u = (ux, uy), N = (Nx, Ny, Nz), c = (cx, cy, cz, cw).
Теперь мы введем четыре специальных трехмерных вектора, которые показаны на рис. Первый из них называется нулевым вектором, и значения всех его компонент равны нулю; мы будем обозначать такой вектор выделенным полужирным шрифтом нулем: 0 = (0, 0, 0). Следующие три специальных вектора называются единичными базовыми векторами (базовыми ортами) трехмерной системы координат. Эти векторы, направленные вдоль осей X, Y и Z нашей координатной системы, мы будем называть i, j и k соответственно. Модуль этих векторов равен единице, а определение выглядит следующим образом: i = (1, 0, 0), j = (0, 1, 0), k = (0, 0, 1).
 | Нулевой вектор и базовые орты трехмерной системы координат |
ПРИМЕЧАНИЕ
Вектор, длина которого равна единице, называется единичным вектором или ортом.
В библиотеке D3DX для представления векторов в трехмерном пространстве мы можем воспользоваться классом TD3DXVECTOR3. Его определение выглядит следующим образом:
_D3DVECTOR = packed record
x: Single;
y: Single;
z: Single;
end {_D3DVECTOR};
{$EXTERNALSYM _D3DVECTOR}
D3DVECTOR = _D3DVECTOR;
{$EXTERNALSYM D3DVECTOR}
TD3DVector = _D3DVECTOR;
{$NODEFINE TD3DVector}
PD3DVector = ^TD3DVector;
{$NODEFINE PD3DVector}
TD3DXVector3 = TD3DVector;
{$NODEFINE TD3DXVector3}
|
Обратите внимание, что TD3DXVECTOR3 наследует компоненты от TD3DVECTOR
ПРИМЕЧАНИЕ
Хотя основной интерес для нас представляют векторы в трехмерном пространстве, занимаясь программированием трехмерной графики мы будем иногда сталкиваться с векторами в двухмерном и четырехмерном пространствах. Библиотека D3DX предоставляет классы TD3DXVECTOR2 и TD3DXVECTOR4, предназначенные для представления векторов в двухмерном и четырехмерном пространствах соответственно. Векторы в пространствах с другим количеством измерений обладают теми же свойствами, что и векторы в трехмерном пространстве, а именно — длиной и направлением, отличается только количество измерений. Кроме того, математические операции с векторами, за исключением векторного произведения (см. раздел «Векторное произведение», далее в этой главе), которое определено только для трехмерной системы координат, могут быть обобщены для векторов любой размерности. Таким образом, за исключением векторного произведения, все операции, которые мы обсуждаем для векторов в трехмерном пространстве, распространяются и на векторы в двухмерном, четырехмерном и даже n-мерном пространствах.
Равенство векторов
В геометрии два вектора считаются равными, если они указывают в одном и том же направлении и имеют одинаковую длину. В алгебре говорят, что векторы равны, если у них одинаковое количество измерений и их соответствующие компоненты равны. Например, (ux, uy, uz) = (vx, vy, vz) если ux = vx, uy = vy и uz = vz.
В коде мы можем проверить равны ли два вектора, используя функцию D3DXVector3Equal :
function D3DXVector3Equal(const v1, v2: TD3DXVector3): Boolean;
|
ПРИМЕЧАНИЕ
Сравнивая числа с плавающей точкой следует быть очень аккуратным, поскольку из-за погрешностей округления, два числа с плавающей точкой, которые должны быть равными, могут слегка отличаться. По этой причине мы проверяем приблизительное равенство чисел с плавающей точкой. Для этого мы определили константу EPSILON, содержащую очень маленькое значение, которое будет служить «буфером». Мы будем говорить, что два числа приблизительно равны, если разница между ними меньше EPSILON. Другими словами, EPSILON дает нам некий допуск для ошибок округления чисел с плавающей точкой. Приведенная ниже функция показывает, как EPSILON может использоваться при проверке равенства двух чисел с плавающей точкой:
function Equals(a,b : single; epsilon : single): boolean;
begin
result:=abs(a-b)<epsilon;
end;
|
Вычисление модуля вектора
В геометрии модулем вектора называется длина направленного отрезка линии. В алгебре, зная компоненты вектора мы можем вычислить его модуль по следующей формуле:
Вертикальные линии в |u| обозначают модуль u.
Вычислите модуль векторов u = (1, 2, 3) и v = (1, 1).
Решение
Для вектора u мы получаем:
Обобщив формулу (1) для двухмерного пространства, для вектора v мы получим:
Работая с библиотекой D3DX, для вычисления модуля вектора мы можем применять следующую функцию:
D3DXVec3Length( // Возвращает модуль
CONST pV: TD3DXVECTOR3; // Вектор, чью длину мы вычисляем
) : single;
|
Нормализация вектора
В результате нормализации получается вектор, направление которого совпадает с исходным, а модуль равен единице (единичный вектор). Чтобы нормализовать произвольный вектор, достаточно разделить каждый компонент вектора на модуль вектора, как показано ниже:
Мы отмечаем единичный вектор, помещая над его обозначением символ ^.
ПРИМЕР
Нормализуйте векторы u = (1, 2, 3) и v = (1, 1).
Решение
Из приведенных выше формул (2) и (3) мы знаем, что |u| = v14 и |v| = v2, поэтому:
В библиотеке D3DX для нормализации векторов применяется следующая функция:
D3DXVec3Normalize(
pOut : TD3DXVECTOR3, // Результат
CONST pV : TD3DXVECTOR3 // Нормализуемый вектор
) : Td3dxVector3;
|
Сложение векторов
Мы можем сложить два вектора, сложив их соответствующие компоненты; обратите внимание, что размерность складываемых векторов должна быть одинаковой:
Геометрическая интерпретация сложения векторов показана на рис.
 | Сложение векторов. Обратите внимание, как мы выполняем параллельный перенос вектора v таким образом, чтобы его начало совпало с концом вектора u; суммой будет вектор начало которого совпадает с началом вектора u, а конец совпадает с концом перенесенного вектора v |
В коде для сложения двух векторов мы будем применять функцию сложения:
function D3DXVec3Add(
out vOut: TD3DXVector3; // сумма векторов
const v1, v2: TD3DXVector3 // слагаемые
): PD3DXVector3;
|
Вычитание векторов
Аналогично сложению, вычитание векторов осуществляется путем вычитания их отдельных компонент. Опять же оба вектора должны иметь одинаковую размерность.
Геометрическая интерпретация вычитания векторов показана на рис.
 | Вычитание векторов |
В коде для вычитания двух векторов мы будем применять функцию вычитания:
function D3DXVec3Subtract(
out vOut: TD3DXVector3; //разность векторов
const v1, v2: TD3DXVector3 // 1-ое и 2-ое слагаемые
): PD3DXVector3;
|
Как видно на рис., операция вычитания векторов возвращает вектор, начало которого совпадает с концом вектора v, а конец — с концом вектора u. Если мы интерпретируем компоненты u и v как координаты точек, то результатом вычитания будет вектор, направленный от одной точки к другой. Это очень удобная операция, поскольку нам часто будет необходимо найти вектор, описывающий направление от одной точки к другой.
Умножение вектора на скаляр
Как видно из названия раздела, мы можем умножать вектор на скаляр, в результате чего происходит масштабирование вектора. Если масштабный множитель положителен, направление вектора не меняется. Если же множитель отрицателен, то направление вектора изменяется на противоположное (инвертируется).
function D3DXVec3Scale(
out vOut: TD3DXVector3;// результат
const v: TD3DXVector3; //сам вектор
s: Single // число, на которое умножить
): PD3DXVector3;
|
Скалярное произведение векторов
Скалярное произведение векторов — это первая из двух определенных в векторной алгебре операций умножения. Вычисляется такое произведение следующим образом:
У приведенной выше формулы нет очевидной геометрической интерпретации. Используя теорему косинусов 1, мы получим отношение UxV = |u||v|cosα , говорящее, что скалярное произведение двух векторов равно произведению косинуса угла между векторами на модули векторов. Следовательно, если u и v — единичные векторы, их скалярное произведение равно косинусу угла между ними.
Вот некоторые полезные свойства скалярного произведения:
- Если u x v = 0, значит u перпендикулярно v.
- Если u х v > 0, значит угол α между двумя векторами меньше 90 градусов.
- Если u x v < 0, значит угол α между двумя векторами больше 90 градусов.
Для вычисления скалярного произведения двух векторов в библиотеке D3DX предназначена следующая функция:
D3DXVec3Dot(
CONST pV1: TD3DXVECTOR3; // Левый операнд.
CONST pV2: TD3DXVECTOR3; // Правый операнд.
) : single;
//////////////////////////////////////////////////////////////
u:=D3DXVECTOR3(1.0, -1.0, 0.0);
v:=D3DXVECTOR3(3.0, 2.0, 1.0);
// 1.0*3.0 + -1.0*2.0 + 0.0*1.0
// = 3.0 + -2.0
dot := D3DXVec3Dot(u, v); // = 1.0
|
Векторное произведение
Второй формой операции умножения, определенной в векторной алгебре, является векторное произведение. В отличие от скалярного произведения, результатом которого является число, результатом векторного произведения будет вектор. Векторным произведением двух векторов u и v будет другой вектор, p, являющийся взаимно перпендикулярным для векторов u и v. Это означает, что вектор p перпендикулярен вектору u и одновременно вектор p перпендикулярен вектору v.
Вычисляется векторное произведение по следующей формуле:
В компонентной форме вычисление выглядит так:
 | Векторное произведение. Вектор p = u x v перпендикулярен как вектору u, так и вектору v |
ПРИМЕР
Вычислите j = k x i = (0, 0, 1) x (1, 0, 0) и проверьте, что вектор j перпендикулярен как вектору i, так и вектору k.
Решение
Таким образом, j = (0, 1, 0). Вспомните, в предыдущем разделе «Скалярное произведение векторов» говорилось, что если u x v = 0, значит u перпендикулярно v. Поскольку j x k = 0 и j x i = 0, мы знаем что вектор j перпендикулярен как вектору k, так и вектору i.
Для вычисления векторного произведения двух векторов в библиотеке D3DX предназначена следующая функция:
D3DXVec3Cross(
pOut : D3DXVECTOR3; // Результат
CONST pV1 : D3DXVECTOR3; // Левый операнд
CONST pV2 : D3DXVECTOR3 // Правый операнд
): TD3DXVector3;
|
Как явствует из рис. , вектор –p также взаимно перпендикулярен векторам u и v. Какой из векторов, p или –p будет возвращен в качестве результата векторного произведения определяется порядком операндов. Другими словами, u х v = –(v х u). Это заначит, что операция векторного произведения не является коммутативной. Определить, какой вектор будет возвращен в качестве результата, можно с помощью правила левой руки. (Мы используем правило левой руки, поскольку работаем с левосторонней системой координат. Если бы у нас была правосторонняя система координат, пришлось бы воспользоваться правилом правой руки.) Если расположить пальцы левой руки вдоль первого вектора, а ладонь руки — вдоль второго, отогнутый на 90 градусов большой палец укажет направление результирующего вектора.
1 Теорема косинусов определяет зависимость между сторонами и углами треугольника. Она утверждает, что во всяком треугольнике квадрат длины стороны равен сумме квадратов двух других сторон без удвоенного произведения длин этих сторон на косинус угла между ними. Если угол прямой, то теорема косинусов переходит в теорему Пифагора, т.к. косинус прямого угла равен 0.
|
 |