Персональная страничка/блог программиста из сибири.

Новые статьи:

Баннеры:

Статьи
Подписаться на RSS.
  Поиск

Программирование трехмерной графики. Часть 2.

2.1. Перемещение - операция Translate.

2.2. Поворот вокруг координатной оси – операция Rotate.

2.3. Масштабирование – операция Scale.

2.4. Итог.

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

2.1. Перемещение - операция Translate.

Как уже понятно из ее названия, перемещает точку в заданном направлении, на заданной расстояние. Допустим, у нас есть точка:

A = {1, 1, 1}. т.е. X = 1, Y = 1, Z = 1;

Рис 2.1.1. Точка с координатами (1, 1, 1)

Что бы переместить ее, например, по оси Z на единицу, нужно проделать вот такою простую операцию:

Z = Z + 1;

У нас получится новая точка с координатами:

A’ = {1, 1, 2}, т.е. X = 1, Y = 1, Z = 2;

Рис 2.1.2. Точка с координатами (1, 1, 2)

Процедуру перемещение точки\вершины на паскале, можно описать следующим образом:


procedure Translate(var AVertex: TVertex; X, Y, Z: Single);
begin
  AVertex.X := AVertex.X + X;
  AVertex.Y := AVertex.Y + Y;
  AVertex.Z := AVertex.Z + Z;
end;

2.2. Поворот вокруг координатной оси – операция Rotate.

Самая сложная по вычислениям операция. А так же самая затратная в плане производительности (на ее тратится в несколько раз больше компьютерных ресурсов, чем на другие операции).

Что бы разобраться как осуществляется поворот геометрических объектов, нужно сначала понять, что такое синус и косинус, а так же разобраться в формуле окружности.

Итак, что бы осуществлять поворот точек, прежде всего нам понадобится две тригонометрические функции:

  • Синус (sin x)
  • Косинус (cos x)

Прежде всего, нам нужно знать, что синус и косинус – это периодические функции, и областью значений этих функций является отрезок [–1; 1]. Т.е. какие-либо значение мы не подставляли бы в данные функции вместо x, например sin 0.1; cos 123, sin 1/2, cos 1.2; - значение функции, всегда будет лежать в интервале от – 1 до 1. Можете это сами проверить на калькуляторе, вычисляя значение этих функций для разных чисел.

Следующим свойством данных функций является их периодичность. Это означает что по мере увеличения аргумента x, эти функция все время будут колебаться в интервале от нуля до единицы. Посмотрите на графики этих функций, рисунок 2.2.1.

Рис 2.2.1. Графики функций sin(x) и cos(x).

На этих графиках видно, что данные функции совершают полное колебательное движение, в интервале значений x: [0; 2pi]. Т.е. при прохождении функций через данный интервал, они опять приходят в исходное положение, которое было при значении x = 0. Потом совершается новое, точно такое же колебательное движение, но уже при x: [2pi; 4pi], и так до бесконечности. Это свойство и называется периодичностью функций.

Что такое число пи (pi) мы сейчас разбирать не будем, нам нужно только знать, что это математическая константа, число с бесконечной дробью, округленное значение которого равно = 3,14.

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

С понятиями синуса и косинуса, тесно связанно понятие окружности. Дело в том, что, по сути, окружность – это тоже колебательная система. Что бы было проще, давайте сначала рассмотри все эти формулы в двухмерной плоскости.

Допустим, что в двухмерной системе координат у нас заданна точка с координатами A(1, 1); Рисунок 2.2.2.

Рис 2.2.2. Точка с координатами A(1, 1).

Так вот, эту точку мы можем вращать вокруг начала координат с помощью этих формул:

Y1 := Y * Cos(Alpha) - X * Sin(Alpha);
X1 := Y * Sin(Alpha) + X * Cos(Alpha);

X, Y – координаты точки. Alpha – угол на который мы хотим повернуть точку, может изменяться от 0 до 2pi. X1, Y1 - новые координаты точки, полученные в результате поворота.

Так же с помощью этих формул, можно легко нарисовать окружность. Достаточно подставлять в данную формулу вместо Alpha значения от 0 до 2pi. У нас получится вот такая картинка: (Рисунок 2.2.3).


Рис 2.2.3. Точка с координатами A(1, 1).

На этом рисунке мы поворачиваем исходную точку A(1, 1) (она у нас черного цвета), каждый раз на 45 градусов, или на значение Alpha = pi / 4. (красные точки). В итоге мы видим, что при полном повороте мы опять пришли в нашу исходную точку A. Также мы видим, что значение Alpha стало равно = 2*Pi или 360 градусов.

Ну вот, мы научились вертеть точки вокруг своей оси в двухмерной плоскости. Как же теперь проделать эту операцию в трехмерной системе координат? Да точно так же! Формулы абсолютно те же! Просто в двухмерной системе координат у нас всего одна плоскость – XY. А в трехмерной, таких плоскостей три: XY, YZ и XZ. Что бы крутить их в данных плоскостях, нужно использовать соответствующие формулы:

Y1 := Y * Cos(Alpha) - X * Sin(Alpha);
X1 := Y * Sin(Alpha) + X * Cos(Alpha);

Z1 := Z * Cos(Alpha) - Y * Sin(Alpha);
Y1 := Z * Sin(Alpha) + Y * Cos(Alpha);

Z1 := Z * Cos(Alpha) - X * Sin(Alpha);
X1 := Z * Sin(Alpha) + X * Cos(Alpha);

Что бы одновременно крутить точки по осям, данные формулы нужно использовать поочередно.

Процедуры поворота точек\вершин на паскале, можно описать следующим образом:



// Поворот по осям XY

procedure RotateXY(var AVertex: TVertex; Alpha: Single);
var
  tX: Single;
  tY: Single;
begin
  tY := AVertex.Y * Cos(Alpha) - AVertex.X * Sin(Alpha);
  tX := AVertex.Y * Sin(Alpha) + AVertex.X * Cos(Alpha);
  AVertex.X := tX;
  AVertex.Y := tY;
end;


// Поворот по осям YZ

procedure RotateYZ(var AVertex: TVertex; Alpha: Single);
var
  tY: Single;
  tZ: Single;
begin
  tZ := AVertex.Z * Cos(Alpha) - AVertex.Y * Sin(Alpha);
  tY := AVertex.Z * Sin(Alpha) + AVertex.Y * Cos(Alpha);
  AVertex.Y := tY;
  AVertex.Z := tZ;
end;


// Поворот по осям XZ

procedure RotateXZ(var AVertex: TVertex; Alpha: Single);
var
  tX: Single;
  tZ: Single;
begin
  tZ := AVertex.Z * Cos(Alpha) - AVertex.X * Sin(Alpha);
  tX := AVertex.Z * Sin(Alpha) + AVertex.X * Cos(Alpha);
  AVertex.X := tX;
  AVertex.Z := tZ;
end;

2.3. Масштабирование.

Пожалуй, самая простая операция. Что выполнить масштабирование, нужно каждую координату точки умножить на соответствующий коэффициент.

A = {X, Y, Z} = {X * k, Y * k, Z * k}

где k - коэффициент масштабирования. Если k > 1 – то размеры масштабируемого объекта увеличиваются, (мы приближаемся к объекту), если K < 1, то соответственно размеры объекта уменьшаются, (отдаляемся от объекта).

Процедуры масштабирования точек\вершин на паскале, можно описать следующим образом:


procedure Scale(var AVertex: TVertex; k: Single);
begin
  AVertex.X := tX * k;
  AVertex.Y := tY * k;
  AVertex.Z := tZ * k;
end;

2.4. Итог.

Итак, мы научились выполнять основные операции по манипуляции точками в пространстве. Осталось только на практике посмотреть, как все это работает. Ниже вы можете скачать исходник Delphi демонстрирующий работу этих трех операций.


Рис 2.4.1. Трехмерная сфера .

В данном примере генерируется трехмерная сфера, которую можно перемещать, вращать и масштабировать.

  • Клавишы: x, y, z - повороты сферы.
  • Клавишы: '+', '-' - масштабирование сферы.
  • Клавишы: вверх, вниз, вправо, влево - перемещение сферы.



18Октября2015|3d
Здравствуйте!

Вы могли бы взглянуть на эти посты:
1. http://stackoverflow.com/questions/33190158/affine-transformation-correct-or-not
2. http://www.cyberforum.ru/windows-forms/thread1535066.html

Я никак не могу понять, почему при вращении объекта, он вращается не относительно глобальной СК, а вокруг своих ребер.

Почему так?
1. Я перенес модель в начало координат:
point.reset()
2. Потом применил приобразования(вот здесь модель должна повернуться относительно глобальной СК)
point.reset().transform(matrix).transform(projection)

И модель какого-то черта вращается вокруг свой СК.

Что не так?
А должна
Сообщение № 5
06Июня2015|юрий
Y1 := Y * Cos(Alpha) - X * Sin(Alpha);
X1 := Y * Sin(Alpha) + X * Cos(Alpha);

Z1 := Z * Cos(Alpha) - Y * Sin(Alpha);
Y1 := Z * Sin(Alpha) + Y * Cos(Alpha);

Z1 := Z * Cos(Alpha) - X * Sin(Alpha);
X1 := Z * Sin(Alpha) + X * Cos(Alpha);
вот тут куда какое вращение идет?
Сообщение № 4
06Июня2015|юрий
опять галопом по европам,
я например никак в толк не возьму
как отобразить точку в трехмерном виде
а Вы тут пишете что все уже научились и все могут
потом ,формулы эти с косинусами и синусами, как
минимум школьную программу знать надо
Сообщение № 3
05Мая2013|пизжец
А кватернионы, ога?
Сообщение № 2
19Мая2012|San4ez
Спасибо большое за статью! Долго искал подходящий ресурс, где можно было бы ознакомится с основными формулами. Пытался вывести их сам, но безуспешно. С некоторыми переработками всё работает безупречно! =)
Сообщение № 1
имя / ник:

e-mail:

Защита от спама:

Введите число, изображенное на картинке:

Текст комментария:

 


WWW.ALEXEYSPACE.RU
(c) alex_ey (Alexey Sokolov)
alex_ey@mail.ru