Новые распродажи в App Store… Transformers CyberToy - для истинных фанатов…
Июл 05

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

Я начну с самого начала — с прямоугольных треугольников — и постепенно подойду к тому, как с помощью круга и треугольника осуществляется поворот в функции “gluLookAt()“.

Прямоугольный треугольник

Я не собираюсь вдаваться в объяснения. Вам нужно знать, что представляет собой прямоугольный (правильный) треугольник, что такое гипотенуза, прилежащие катеты и противолежащий катет. Чтобы все мы придерживались единой терминологии, приведу изображение с терминами:

Гипотенуза (hypotenuse)
Противолежащий (opposite)
Прилежащий (adjacent)

Предлагаю вспомнить все, пройденное в старших классах школы, а после забытое за ненадобностью. Длину любой стороны легко узнать по следующим формулам:

Гипотенуза: гипотенуза2 = прилежащий катет2 + противолежащий катет2
в С: hypoenuse = sqrt(adjacent*adjacent + opposite*opposite);

Длина прилежащего катета: косинус (Ɵ) * гипотенузу
в С: adjacent = cos(angleInRadians) * hypotenuse;

Длина противолежащего катета: синус (Ɵ) * гипотенузу
в C: oppositeLength = sin(angleInRadians) * hypotenuse.

Для начала запомните, что математические функции С работают не с градусами, а с радианами. Волновать это особенно не должно — главное знать два макроса для преобразования:

1
2
#define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(__RADIANS) ((__RADIANS) * 180 / M_PI)

Вот как легко запомнить соотношение между радианами и градусами: в круге 360º или 2 х π радиана. Соответственно, полукруг равен π радианам.

Согласно математической библиотеке GCC, M_PI в файле “math.h” определяется как 3.14-любое значение. Стандарту С это не совсем соответствует — возможностей для определения числа пи здесь нет. Технически, от вас требуется самостоятельный расчет, поэтому соблюдайте максимально возможную для конкретной аппаратной реализации точность (это всего лишь acos(-1) от памяти). Занимаясь программированием столько лет, я всегда за недостатком времени обходился исключительно определенными значениями.

Если не можете вспомнить принцип работы функций sin(), cos() и tan() — не страшно. Не обязательно знать особенности двигателя внутреннего сгорания, чтобы водить машину — главное знать, как (и когда) его задействовать.

Возвращаемся к программированию графики

Если помните, обсуждая в прошлом уроке перемещения и повороты в 3D, я сравнивал этот процесс с рисованием круга. Сейчас остановится на этом моменте подробнее, построив этот самый круг.

Ниже изображен круг с двумя отложенными на нем точками.

Ничего не заметили? Взгляните еще раз.

Ну конечно же, прямоугольные треугольники!

Зная радиус и угол, можно вычислить положение любой точки на окружности. А уже располагая этими данными — приступать к рисованию круга.

Мы знаем длину гипотенузы, поскольку она равна радиусу круга. Осталось вычислить точки X и Y. С учетом приведенных выше функций для синего треугольника координата X будет прилегающим катетом, а Y — противоположным.

Само собой, прилегающая и противоположная стороны меняются в зависимости от сектора, но пока этот момент не должен нас волновать. Код рисования круга:

1
2
3
4
5
for (angle = 0; angle < 2*M_PI; angle += 0.01) {
point[0] = RADIUS * cos(angle);
point[1] = RADIUS * sin(angle);
glDrawArrays(GL_POINTS, 0, 1);
}

Не забывайте, что значения sin() и cos() передаются не в градусах, а в радианах (в круге 360º или 2 х π радиана). Чем меньше прирост угла в рамках цикла, тем аккуратнее формируется круг. Для получения красивых, ровных кругов по большей части достаточно не точек, а очень коротких линий.

Переходим от кругов к поворотам из прошлого урока

Для определения объекта взгляда в трехмерном пространстве на прошлом уроке мы использовали функцию “glLookAt()“. Именно тогда я и сравнил ее работу с рисованием круга.

Если сейчас пользователь решит повернуться в направлении против часовой стрелки, результат будет следующим:

Уверен, все поняли, куда я клоню — к описанию круга посредством правильных треугольников. :)

Надеюсь, никто не забыл, что у нас была локация взгляда и направление взгляда. Локация взгляда не меняется — при повороте взгляд перемещается по окружности.

Код выглядел следующим образом:

1
2
3
4
facing[0] = position[0] + cos(-TURN_SPEED)*vector[0] -
sin(-TURN_SPEED)*vector[2];
facing[2] = position[2] + sin(-TURN_SPEED)*vector[0] +
cos(-TURN_SPEED)*vector[2];

Переменная “facing” — объект взгляда, точка на окружности. Переменная “position” — положение зрителя, точка, из которой исходит взгляд. В трехмерном пространстве все несколько сложнее по сравнению с рисунком на плоском листе бумаги. Даже не рассчитывая жестко зафиксированную координату Y, мы должны узнать координаты X и Z.

Урок окончен

Вот мы и рассмотрели эту тему подробнее. В следующем уроке вернемся к основной теме — как только мне удастся подобрать подходящий фрагмент бесплатного кода.

Поскольку на этот раз мы ограничились исключительно теорией, кода к уроку не будет.

Текст оригинальной статьи на английском языке [здесь]

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

1 звезда2 звезд3 звезд4 звезд5 звезд (1 голосов, средний: 5.00 из 5)
Загрузка ... Загрузка ...


5 Responses to “Уроки iPhone SDK: (Часть 14) OpenGL ES: Перемещение в 3D: теория (Часть 2)”

  1. 1. Arthur Says:

    opposite = Противолежащий (под изображением [1])

  2. 2. Artem Says:

    Исправил, спасибо.

  3. 3. loxx45 Says:

    если будет время,переведите пожалуйста вот эти статьи

    http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/6/17_OpenGL_ES_14_-_Getting_Access_to_Blender_Models__Part_1.html

    http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/7/25_OpenGL_ES_17_-_Collision_Detection.html

  4. 4. Artem Says:

    Хорошо. Займемся.

  5. 5. Aleksey Says:

    Напишите пожалуйста про отображение поверхностей, например поверхностей Безье

Оставьте комментарий