OpenGL SuperBible (6th Edition) / OpenGL Супер Книга (6-ое издание): Математика для 3D-графики

← →
Английский оригинал Перевод на русский

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

Поэтому мы можем переписать это уравнение следующим образом

P = A + t (B – A) or
P = (1 – t) A + tB

vk955 07.09.14 в 09:33

0

Легко увидеть, что при t равном нулю, P равна A, а когда t равен единице, P равен A + B – A, т.е. просто B. Такая линия показана на рисунке 4.13.

vk955 07.09.14 в 09:33

0

Рисунок 4.13: Нахождение точки на линии

vk955 07.09.14 в 09:33

0

Если t лежит между 0.0 и 1.0, то Р будет в конечном итоге лежать где-то между А и В. Значения t за пределами этого диапазона будет выталкивать P за концы линии. Вы должны видеть, что путем плавного изменения t, мы можем двигаться точку Р из А в В и обратно. Это называется линейной интерполяцией. Значения A и B (и, следовательно, P) может иметь любое число измерений. Например, они могут быть скалярными значениями; двумерными значениями вроде точек на графике; трехмерными значениями вроде координат в трехмерном пространстве, значениями цветов и т.д.; или величинами даже более высокой размерности вроде матриц, массивов и даже целыми изображениями. Во многих случаях, линейная интерполяция не имеет особого смысла (например, линейная интерполяция между двумя матрицами, как правило, не дает значимого результата), но углы, позиции и координаты обычно можно интерполировать безопасно.

vk955 07.09.14 в 09:35

0

Линейная интерполяция - настолько распространенная операция в графике, что GLSL имеет встроенную функцию mix специально для этой цели:

vk955 07.09.14 в 09:35

0

vec4 mix(vec4 A, vec4 B, float t);

vk955 07.09.14 в 09:35

0

Функция mix имеет несколько версий, которые принимают векторы различной размерности или скаляры во входных параметрах А и В, а также принимают скаляры или соответствующие вектора в параметре t.

vk955 07.09.14 в 09:36

0

Кривые
Если перемещать все вдоль прямой линии между двумя точками - это все, что мы хотим делать, то этой информации будет достаточно. Однако, в реальном мире, объекты движутся по гладким кривым, плавно ускоряясь и замедляясь. Кривая может быть представлена ​​тремя или более контрольными точками. Для большинства кривых, определено более трех контрольных точек, две из которых образуют концевые точки, а остальные задают форму кривой. Рассмотрим простой кривую, показанную на рисунке 4.14.

vk955 07.09.14 в 09:39

0

Рисунок 4.14: простая кривая Безье

vk955 07.09.14 в 09:39

0

Кривая, показанная на рисунке 4.14, имеет три контрольные точки A, B и C. А и С являются концевыми точками кривой, а В определяет форму кривой. Если мы соединим точки А и В одной линией, а точки В и С другой, то мы сможем произвести интерполяцию вдоль двух линий, используя простую линейную интерполяцию, чтобы найти новую пару точек D и E. Теперь, имея эти две точки, мы можем, соединив их с помощью еще одной линии, произвести вдоль нее интерполяцию и найти новые точку P. И пока мы будем изменять наш параметр интерполяции t, точка P будет двигаться по гладкой криволинейной траектории от А до D. Выразив это математически, получим

D = A + t(B – A)
E = B + t(C – B)
P = D + t(E – D)

vk955 07.09.14 в 09:43

0

Сделав подстановку вместо D и E и сократив формулу, мы получим следующее:

P = A + t(B – A) + t((B + (t(C – B))) – (A + t(B – A))))
P = A + t(B – A) + tB + t2(C – B) – tA – t2(B – A)
P = A + t(B – A + B – A) + t2(C – B – B + A)
P = A + 2t(B – A) + t2(C – 2B + A)

vk955 07.09.14 в 09:43

0

Вы должны узнать в этой формуле квадратное уравнение с переменной t. Кривая, которую описывает данное уравнение, известна как квадратичная кривая Безье. На самом деле, в GLSL мы можем реализовать этот функционал очень легко благодаря функции mix, так как все, что мы делаем, является линейной интерполяцией результатов двух предыдущих интерполяций.

vk955 07.09.14 в 09:44

0

vec4 quadratic_bezier(vec4 A, vec4 B, vec4 C, float t)
{
vec4 D = mix(A, B, t); // D = A + t(B - A)
vec4 E = mix(B, C, t); // E = B + t(C - B)
vec4 P = mix(D, E, t); // P = D + t(E - D)
return P;
}

vk955 07.09.14 в 09:44

0

Добавив четвертую контрольную точку, как показано на рисунке 4.15, мы можем увеличить порядок кривой на единицу и получить кубическую кривую Безье.

vk955 07.09.14 в 09:44

0

Рисунок 4.15: кубическая кривая Безье

vk955 07.09.14 в 09:45

0

Теперь у нас есть четыре контрольные точки A, B, C и D. Способ построения кривой аналогичен построению квадратичной кривой Безье. Мы строим первую линию от A до B, вторую от B к C, третью от С до D. Интерполирование вдоль всех из трех линий порождает три новые точки E, F и G. Используя эти три точки, мы формируем еще две линии: одну от E до F, а другую от F до G, интерполирование вдоль которых порождает точки H и I, между которыми мы можем произвести еще одну интерполяцию, чтобы найти наш конечную точку P. Таким образом, наше уравнение будет выглядеть как показано ниже.

E = A + t(B – A)
F = B + t(C – B)
G = C + t(D – C)
H = E + t(F – E)
I = F + t(G – F)
P = H + t(I – H)

vk955 07.09.14 в 09:47

0

Если вам показалось, что уравнения выше выглядят знакомо, вы правы - наши точки E, F и G образуют квадратичную кривую Безье, которую теперь мы используем при интерполяции для нахождения нашей конечной точки P. Если бы мы должны были подставить уравнения для точек E, F и G в уравнения для точек H и I, а те, в свою очередь, подставив в уравнение для P и раскрывая скобки, мы получим кубическое уравнение (“кубическое” означает t3). Опять же, в GLSL мы можем осуществить это просто и эффективно с точки зрения линейной интерполяцией благодаря функции mix:

vk955 07.09.14 в 09:50

0

vec4 cubic_bezier(vec4 A, vec4 B, vec4 C, vec4 D, float t)
{
vec4 E = mix(A, B, t); // E = A + t(B - A)
vec4 F = mix(B, C, t); // F = B + t(C - B)
vec4 G = mix(C, D, t); // G = C + t(D - C)
vec4 H = mix(E, F, t); // H = E + t(F - E)
vec4 I = mix(F, G, t); // I = F + t(G - F)
vec4 P = mix(H, I, t); // P = H + t(I - H)
return P;
}

vk955 07.09.14 в 09:50

0

Так же, как структура уравнений для кубической кривой Безье "включает в себя" уравнения для квадратичной кривой, так и код для ее реализации будет включать в себя код для реализации кривой меньшей степени. На самом деле, мы можем наложить эти кривые друг на друга, используя код для одной, чтобы построить следующую:

vk955 07.09.14 в 09:51

0

vec4 cubic_bezier(vec4 A, vec4 B, vec4 C, vec4 D, float t)
{
vec4 E = mix(A, B, t); // E = A + t(B - A)
vec4 F = mix(B, C, t); // F = B + t(C - B)
vec4 G = mix(C, D, t); // G = C + t(D - C)
return quadratic_bezier(E, F, G, t);
}

vk955 07.09.14 в 09:51

0

Теперь, когда у нас есть этот пример, мы можем действовать по аналогии, чтобы строить кривые еще более высоких степеней. К примеру, кривая Безье пятой степени (с пятью контрольными точками) может быть реализована следующим образом

vk955 07.09.14 в 09:52

0

vec4 quintic_bezier(vec4 A, vec4 B, vec4 C, vec4 D, vec4 E, float t)
{
vec4 F = mix(A, B, t); // F = A + t(B - A)
vec4 G = mix(B, C, t); // G = B + t(C - B)
vec4 H = mix(C, D, t); // H = C + t(D - C)
vec4 I = mix(D, E, t); // I = D + t(E - D)
return cubic_bezier(F, G, H, I, t);
}

vk955 07.09.14 в 09:52

0

Это наложение теоретически может использоваться снова и снова для любого количества контрольных точек. Однако, на практике, кривые более, чем четвертой степени обычно не используются. Лучше мы используем сплайны.

vk955 07.09.14 в 09:53

0

Сплайны
Сплайн - это фактически длинная кривая состоящая из нескольких небольших кривых (например, Безье). Как минимум, контрольные точки, представляющие концы кривых, разделены между сегментами,[*] и часто одна или более внутренняя контрольная точка одного сегмента является общей или связанной, тем или иным образом, с соседним сегментом. Любое количество кривых может быть соединено вместе этим способом, позволяя формировать сколь угодно длинные линии. Взгляните на кривую, изображенную на рисунке 4.16.

--------
Это то, что (скрепляет / сцепляет) кривые вместе для формирования сплайна. Эти контрольные точки известны как швами (welds), а контрольные точки, находящиеся между ними, иногда называют узлами.

vk955 07.09.14 в 09:56

0

Рисунок 4.16: Кубический сплайн Безье

vk955 07.09.14 в 09:57

0

На рисунке 4.16, кривая определена десятью контрольными точками, от А до J, которые образуют три кубических кривых Безье. Первая определена точками A, B, C и D; вторая образована общей точкой D, а также E, F и G; третья начинается с общей G, за которой идут H, I и J. Этот тип сплайна известен как кубический сплайн Безье, потому что построен из последовательности кубических кривых Безье. Он также называется кубическим B-сплайном - термин, который может быть знаком тем, кто раньше уже читал что-то о графике.

Для интерполяции точки P вдоль сплайна, мы просто разделим его на три части, допуская изменение значения t в диапазоне от 0.0 до 3.0. Между 0.0 и 1.0, мы интерполируем вдоль первой кривой, переходя от А до D. Между 1.0 и 2.0, мы интерполируем вдоль второй кривой, переходя от D до G, а когда t изменяется от 2.0 до 3.0, мы интерполируем вдоль последней кривой между точками G и J.

vk955 07.09.14 в 09:59

0

Таким образом, целая часть значения t определяет сегмент кривой, вдоль которого мы осуществляем интерполяцию, а дробная часть используется для интерполяции вдоль этого сегмента. Конечно, мы можем масштабировать t, как захотим. Например, если мы возьмем значение между 0.0 и 1.0 и умножим его на количество сегментов в кривой, мы сможем продолжать использовать наш исходный диапазон значений t независимо от количества контрольных точек в кривой.

Следующий код будет интерполировать вектор вдоль кубического сплайна Безье с десятью контрольными точками (и, следовательно, тремя сегментами):

vk955 07.09.14 в 10:00

0

vec4 cubic_bspline_10(vec4 CP[10], float t)
{
float f = t * 3.0;
int i = int(floor(f));
float s = fract(t);
if (t <= 0.0)
return CP[0];
if (t >= 1.0)
return CP[9];
vec4 A = CP[i * 3];
vec4 B = CP[i * 3 + 1];
vec4 C = CP[i * 3 + 2];
vec4 D = CP[i * 3 + 3];
return cubic_bezier(A, B, C, D, s);
}

vk955 07.09.14 в 10:00

0

Если мы используем сплайн для определения положения или ориентации объекта, мы должны быть очень осторожны при выборе позиций контрольных точек, чтобы сохранить движение плавным. Частота изменения значения нашей интерполированной точки P (скорость) является дифференциалом уравнения кривой относительно t. Кроме того, частота изменения скорости P (ускорение) является производной второго порядка уравнения сплайна относительно t. Если ускорение не плавное, то P станет внезапно ускоряться или замедляться.

vk955 07.09.14 в 10:01

0

Функция, которая имеет непрерывную первую производную называется C1-непрерывной, и аналогично кривая, которая имеет непрерывную вторую производную называется C2-непрерывной. Сегменты кривой Безье являются C1- и C2-непрерывными, но для того, чтобы убедиться, что мы сохраняем преемственность над швами (welds) сплайна, мы должны убедиться, что каждый сегмент начинается с условиями, при которых предыдущий заканчивается, а именно: в положении, направлении движения и частоте изменения. Итак, частота перемещения в определенном направлении - это просто скорость. Таким образом, вместо того, чтобы назначать произвольные контрольные точки нашему сплайну, мы можем назначить скорость в каждом weld. Если одинаковая скорость кривой в каждом weld используется для вычисления сегментов кривой по обе стороны от этого weld, то мы будем иметь сплайн-функцию, которая является одновременно и C1-, и C2-непрерывной.

vk955 07.09.14 в 10:05

0

Вы все поймете, если еще раз взглянете на рисунок 4.16 - перегибов нет, кривая красиво и плавно проходит через welds (точки D и G). Теперь посмотрим на контрольные точки по обе стороны от welds. Для примера, возьмем точки С и E, которые окружают D. С и E образуют прямую линию, а D находится прямо в середине нее. На самом деле, мы можем назвать отрезок от D до E скоростью в D, или Vd. Имея положение точки D (weld) и скорости кривой Vd в D, точки С и Е могут быть рассчитаны так

vk955 07.09.14 в 10:07

0

Аналогично, если Va является скоростью в A, то B может быть рассчитано так

vk955 07.09.14 в 10:07

0

Таким образом, вы можете видеть, что, имея положения и скорости в welds кубического B-сплайна, мы можем обойтись без других контрольных точек, вычисляя их на лету также, как мы вычисляем каждую контрольную точку. Кубический B-сплайн, определенный подобным образом (в виде набора положений и скоростей weld), известен как кубический эрмитов сплайн (cubic Hermite spline, cspline). Это чрезвычайно полезный инструмент для получения плавной и естественной анимации.

vk955 07.09.14 в 10:10

0

Заключение
В этой главе вы изучили некоторые математические концепции, имеющие решающее значение при использовании OpenGL для создания 3D-сцен. Даже если вы пока не можете жонглировать матрицами в голове, вы теперь знаете, что они представляют из себя и как используются для выполнения различных преобразований. Вы также узнали, как построить и обращаться с матрицами, которые задают свойства наблюдателя и области просмотра. Теперь вы должны понять, как размещать свои объекты в сцене и определять, как они будут представляться на экране. В этой главе была также представлена мощная концепция систем отсчета: вы увидели, как легко ими можно манипулировать и задавать на их основе преобразования.

vk955 07.09.14 в 10:12

0

Наконец, мы показали, как использовать библиотеку vmath, которая поставляется вместе с этой книгой. Эта библиотека, написанная полностью на переносимом C++, предоставляет вам удобный инструментарий из различных математических и прочих вспомогательных функций, которые могут быть использованы вместе с OpenGL.

vk955 07.09.14 в 10:13

0

Удивительно, но в этой главе мы не рассмотрели ни одной новой для нас OpenGL-функции. Да, эта глава была о математике, и вы могли даже не заметить этого, если считаете, что математика - это только формулы и расчеты. Векторы и матрицы абсолютно необходимы для того, чтобы вы смогли использовать OpenGL для отрисовки трехмерных миров и объектов. Тем не менее, важно отметить, что OpenGL не налагает никаких особых условий на использование математики, как и не содержит никакой реализации математических функций. Даже если вы используете другую математическую библиотеку, или даже написали свою собственную, она вы все равно будет построена на основе тех концепций, что были изложены в этой главе. А теперь двигаемся вперед и начинаем что-то делать!

vk955 07.09.14 в 10:14

0
Минутку...

← Предыдущая страница