#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:
Я вижу две проблемы с вашим кодом. Оба исправлены с небольшим изменением.
-
Вы пытаетесь применить операцию вращения, принимая координаты X и Y в качестве входных данных и получая новые X и Y в качестве выходных данных. Для каждой вращаемой вершины у вас есть две строки кода: первая вычисляет координату X, вторая — координату Y. Но при вычислении координаты Y вы используете уже повернутую координату X! Это неправильно.
-
Существует также числовая проблема. Вы повторно используете старые значения снова и снова, что приводит к цепочке вычислений вращения, которые выполняет значение, поэтому числовые ошибки суммируются. Никогда не полагайтесь на такие вычисления, чтобы работать должным образом. Вместо этого вы должны работать с исходными значениями и увеличивать угол в каждом кадре. Это гарантирует, что каждое значение участвовало только в одном вычислении вращения.
Для устранения обеих проблем сохраните исходные координаты где-нибудь в своем коде, я называю их 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… Большое вам спасибо, теперь это работает.