Нахождение точек треугольника после вращения - PullRequest
4 голосов
/ 01 октября 2010

Я работаю над (довольно) простым 2D проектом в OpenGL. Это какой-то клон астероидов.

Корабль в основном представляет собой равнобедренный треугольник высотой H, а основание имеет длину H / 2.

То, как я делал это до сих пор, - это просто сохранение центральной точки (CP) треугольника, а затем вычисление окончательных положений вершин на лету. «Точка» корабля (векторы x, y) (CP.x, CP.y + H / 2). Двумя другими точками являются (CP.X - H / 4, CP.Y - H / 2) и (CP.X + H / 4, CP.Y - H / 2).

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

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

Я пытался использовать правило косинуса, чтобы найти расстояние между не повернутым треугольником и треугольником после вращения. В качестве примера, вот как я пытался вычислить «остроконечную» позицию вершины после поворота:

//pA is a vector struct holding the position of the pointy vertex of the ship (centerPoint.x, centerPoint.y + height / 2)

//Distance between pA and the rotated pointy vertex - using the cosine rule
float distance = sqrt((2 * pow(size / 2, 2)) * (1 - cosf(rotAngle)));

//The angle to the calculated point
float newPointAngle = (M_PI / 2) - rotAngle;
float xDif = distance * cosf(newPointAngle);
float yDif = distance * sinf(newPointAngle);

//Actually drawing the new point
glVertex2f(pA.x - xDif, pA.y - yDif);

Есть идеи, что я могу делать не так?

Ответы [ 3 ]

4 голосов
/ 01 октября 2010

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

Пост от estain на форумах GameDev добился цели. Чтобы процитировать его сообщение (извините за c & p, но может быть полезно для кого-то, кто сталкивается с подобной проблемой):

Не углубляясь в общие решения и математику (как уже упоминалось выше в постерах и множестве статей), я мог бы дать вам пример того, как решить проблему, «поворачивая точку A вокруг точки B на C градусов ».

Теперь. Прежде всего, как я описал в предыдущем посте, точка, которая находится на оси X, расстояние L от ориг., Повернута на C градусов вокруг ориг. На

x = L * cos (C)

y = L * sin (C)

Аналогичным образом формула для перпендикулярного вектора имеет вид x = -y | y = x, что означает, что точка, которая находится на оси Y (опять же, L из оригинала), будет вращаться на C по формуле

x = - L * sin (C)

y = L * cos (C)

Как показано на рисунке выше, окончательное решение представляет собой сумму поворотов проецируемых векторов, поэтому мы можем вывести формулу

x '= x * cos (C) - y * sin (C)

y '= y * cos (C) + x * sin (C)

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

первый шаг; переместить исходную точку.

x '= A.x - B.x

y '= A.y - B.y

второй шаг, выполнить вращение

x '' = x '* cos (C) - y' * sin (C) = (A.x-B.x) * cos (C) - (A.y-B.y) * sin (C)

y '' = y '* cos (C) + x' * sin (C) = (A.y-B.y) * cos (C) + (A.x-B.x) * sin (C)

третий и последний шаг, сдвинуть назад координатную рамку

x '' '= x' '+ B.x = (A.x-B.x) * cos (C) - (A.y-B.y) * sin (C) + B.x

y '' '= y' '+ B.y = (A.y-B.y) * cos (C) + (A.x-B.x) * sin (C) + B.y

И престо! у нас есть формула вращения. Я дам вам это без всех этих> вычислений:

Вращение точки A вокруг точки B на угол C

A.x '= (A.x-B.x) * cos (C) - (A.y-B.y) * sin (C) + B.x

A.y '= (A.y-B.y) * cos (C) + (A.x-B.x) * sin (C) + B.y

Если вы следили за мной здесь (а я довольно паршивый учитель, извините, если вы этого не сделали), вы можете заметить, что порядок выполнения этих операций очень важен. Попробуйте смешать шаги 3 и 1 и увидите разницу в формулах, которые вы получаете.

Удачи и всего!

2 голосов
/ 01 октября 2010

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

Затем используйте новые точки для получения повернутых координат:

x1 = x cos f - y sin f
y1 = y cos f + x sin f

где f - угол поворота.

Затем вы переводите новые координаты туда, откуда вы начали (обратная сторона первого перевода.

Выезд эта статья для некоторых диаграмм и пояснений.

1 голос
/ 01 октября 2010

Расчет новых баллов относительно прост. Предположим, что x и y являются координатами определенной точки на треугольнике (то есть вершины) относительно точки вращения (или центра).

Вы должны преобразовать координаты в квадратную составляющую расстояния и угла:

float dist, angle;
dist = (x*x) + (y*y);
angle = atan(abs(x)/abs(y));
// a little more code is required for the different quadrants that the angle could be in.

Затем поверните:

angle+=rotation_angle;

Затем преобразовать обратно:

new_x = sqrt(dist)*sin(angle*pi/180);
new_y = sqrt(dist)*cos(angle*pi/180);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...