Вращать треугольник непрерывно

#java #opengl #opengl-es-2.0

#java #opengl #opengl-es-2.0

Вопрос:

У меня есть float[] newCoords переменная, размер которой равен 9. Первые 3 записи представляют одну вершину, следующие 3 представляют вторую вершину, а последние 3 представляют последнюю вершину.

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

 float s = (float) Math.sin(0.5);
float c = (float) Math.cos(0.5);

float[] centroid = getCentroid(newCoords);

newCoords[0] -= centroid[0];
newCoords[1] -= centroid[1];
newCoords[3] -= centroid[0];
newCoords[4] -= centroid[1];
newCoords[6] -= centroid[0];
newCoords[7] -= centroid[1];

newCoords[0] = (newCoords[0] * c) - (newCoords[1] * s);
newCoords[1] = (newCoords[0] * s)   (newCoords[1] * c);

newCoords[3] = (newCoords[3] * c) - (newCoords[4] * s);
newCoords[4] = (newCoords[3] * s)   (newCoords[4] * c);

newCoords[6] = (newCoords[6] * c) - (newCoords[7] * s);
newCoords[7] = (newCoords[6] * s)   (newCoords[7] * c);

newCoords[0]  = centroid[0];
newCoords[1]  = centroid[1];
newCoords[3]  = centroid[0];
newCoords[4]  = centroid[1];
newCoords[6]  = centroid[0];
newCoords[7]  = centroid[1]; 
  

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

РЕДАКТИРОВАТЬ: упс, чуть не забыл, вот мой getCentroid() метод.

 private float[] getCentroid(float[] p1) {
    float[] newCoords = new float[] {(p1[0]   p1[3]   p1[6]) / 3.0f,
                                     (p1[1]   p1[4]   p1[7]) / 3.0f, 0};
    return newCoords;
}
  

Комментарии:

1. Для меня это похоже на Java…

2. @leemes мой плохой. Его 1 час ночи здесь xD

Ответ №1:

Я вижу две проблемы с вашим кодом. Оба исправлены с небольшим изменением.

  1. Вы пытаетесь применить операцию вращения, принимая координаты X и Y в качестве входных данных и получая новые X и Y в качестве выходных данных. Для каждой вращаемой вершины у вас есть две строки кода: первая вычисляет координату X, вторая — координату Y. Но при вычислении координаты Y вы используете уже повернутую координату X! Это неправильно.

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

Для устранения обеих проблем сохраните исходные координаты где-нибудь в своем коде, я называю их coords , и перепишите код так, чтобы вы принимали этот массив в качестве входных данных (сохраняйте newCoords в качестве выходных данных). Увеличивайте угол поворота в каждом кадре, чтобы добиться анимации поворота.

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

Псевдокод:

 // initial:
angle = 0.0;
coords = (initial coordinates)

// per frame:
angle  = 0.5;
newCoords = rotate(coords, angle);
draw(newCoords);
  

Кроме того, обратите внимание, что 0.5 это большой угол, если вы хотите поворачивать на этот угол кадр за кадром. Математические функции ожидают угол в радианах (не градусах), поэтому вы можете использовать меньшее значение в зависимости от того, что вы хотите визуализировать в частности.

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

Комментарии:

1. Я вращаюсь на постоянные 0,2 радиана каждые 100 миллисекунд. Метод rotate просто не вращает его должным образом, я не знаю, почему он уменьшает размер треугольника.

2. @Clay Подождите, есть еще одна проблема с вашим кодом, которая, вероятно, является основной причиной. Позвольте мне это исправить.

3. @Clay Хорошо, теперь, пожалуйста, посмотрите на мой ответ еще раз, пункт 1. очень важно. Предлагаемое мной изменение должно устранить обе проблемы.

4. Пожалуйста, не применяйте исправления, предложенные в ответах на ваш первоначальный вопрос. Это потому, что это делает мой ответ недействительным (он больше не соответствует вопросу). Я верну ваше редактирование вопроса. Проблема в вашем текущем коде заключается в том, что у вас есть p1, p2, p2 (вместо p1, p2, p3 ) в формулах для новых значений. Кроме того, вы только исправили проблему 1, о которой я упоминал, а не проблему 2 (у вас все еще есть эта цепочка вычислений).

5. Боже мой, как я не видел, что p1 p2 p2… Большое вам спасибо, теперь это работает.