Шейдер OpenGL-вращение модели вокруг ее начала координат (2D мир)
Поэтому я создал вершинный шейдер, который принимает угол и вычисляет поворот. Однако существует проблема, что модель вращается вокруг центра мира, а не вокруг своей собственной оси/начала координат.
Боковое Примечание: это 2D вращение.
Как заставить модель вращаться вокруг своей оси?
Вот мой текущий вершинный шейдер:
#version 150 core
in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;
out vec4 pass_Color;
out vec2 pass_TextureCoord;
void main(void) {
gl_Position = in_Position;
pass_Color = in_Color;
pass_TextureCoord = in_TextureCoord;
}
Вращающаяся сторона процессора:
Vector3f center = new Vector3f(phyxBody.getPosition().x,phyxBody.getPosition().y,0);
Matrix4f pos = new Matrix4f();
pos.m00 = (phyxBody.getPosition().x)-(getWidth()/30f/2f);
pos.m01 = (phyxBody.getPosition().y)+(getHeight()/30f/2f);
pos.m10 = (phyxBody.getPosition().x)-(getWidth()/30f/2f);
pos.m11 = (phyxBody.getPosition().y)-(getHeight()/30f/2f);
pos.m20 = (phyxBody.getPosition().x)+(getWidth()/30f/2f);
pos.m21 = (phyxBody.getPosition().y)-(getHeight()/30f/2f);
pos.m30 = (phyxBody.getPosition().x)+(getWidth()/30f/2f);
pos.m31 = (phyxBody.getPosition().y)+(getHeight()/30f/2f);
pos.rotate(phyxBody.getAngle(),center);
Результат-странный повернутый участок объекта.. И знаете почему? Не беспокойтесь о части /30f.
- phyxBody-это экземпляр класса Body из библиотеки JBox2D. phyxBody.getAngle() находится в raidians.
- Matrix4f-это класс из библиотеки LWJGL.
Правка:
Vector3f center = new Vector3f(0,0,0);
Matrix4f pos = new Matrix4f();
pos.m00 = -(getWidth()/30f/2f);
pos.m01 = +(getHeight()/30f/2f);
pos.m10 = -(getWidth()/30f/2f);
pos.m11 = -(getHeight()/30f/2f);
pos.m20 = +(getWidth()/30f/2f);
pos.m21 = -(getHeight()/30f/2f);
pos.m30 = +(getWidth()/30f/2f);
pos.m31 = +(getHeight()/30f/2f);
pos.rotate(phyxBody.getAngle(),center);
pos.m00 += phyxBody.getPosition().x;
pos.m01 += phyxBody.getPosition().y;
pos.m10 += phyxBody.getPosition().x;
pos.m11 += phyxBody.getPosition().y;
pos.m20 += phyxBody.getPosition().x;
pos.m21 += phyxBody.getPosition().y;
pos.m30 += phyxBody.getPosition().x;
pos.m31 += phyxBody.getPosition().y;
В настоящее время это код преобразования, но вращение все еще не работает правильно.
Моя попытка в методе поворота: (что я делаю не так?)
if (phyxBody.getAngle() != 0.0) {
pos.m00 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
pos.m01 *= Math.sin(Math.toDegrees(phyxBody.getAngle()));
pos.m10 *= -Math.sin(Math.toDegrees(phyxBody.getAngle()));
pos.m11 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
pos.m20 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
pos.m21 *= Math.sin(Math.toDegrees(phyxBody.getAngle()));
pos.m30 *= -Math.sin(Math.toDegrees(phyxBody.getAngle()));
pos.m31 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
}
2 ответа:
Порядок масштабирования * вращение * перевод - см.этот вопрос . Я предполагаю, что вы уже перевели свои координаты за пределы вашего шейдера. Вам придется сначала повернуть, а потом перевести. Хорошо знатьлинейную алгебру за тем, что вы делаете, чтобы вы знали, Почему вещи работают или не работают.
Типичный способ сделать это-передать предварительно вычисленную матрицу ModelView, которая уже позаботилась о масштабировании/вращении/трансляции. Если вы уже переведя ваши вершины, вы не можете решить проблему в вашем шейдере без необходимости его отмены, а затем повторного выполнения. Отправляйте свои вершины непереведенными и сопровождайте их данными, такими как ваш угол, чтобы перевести их. или Вы можете перевести и повернуть оба заранее. Это зависит от того, что вы хотите сделать.Итог: Вы должны вращаться, прежде чем переводить.
Вот типичный способ преобразования вершин:
OpenGL сторона:
Вычислить матрицу ModelView: масштаб * вращение * перевод
Переход к шейдеру в виде однородной матрицы
Сторона GLSL:
Умножение вершин на матрицу ModelView в вершинном шейдере
Отправить в
gl_Position
Ответ на редактирование:
Я склонен думать, что ваша реализация должна быть полностью переделана. У вас есть точки, которые принадлежат модели. Эти пункты все ориентирован вокруг источника. Например, если бы у вас был автомобиль, точки образовали бы сетку треугольников.
Если вы просто не переведете эти точки, а затем повернете их, автомобиль будет вращаться вокруг своего центра. Если вы переведете позже, автомобиль будет переведен в своем вращенном виде в указанное вами место. Ключ здесь в том, что начало вашей модели совпадает с началом вращения, так что вы в конечном итоге вращаете модель "вокруг себя."
Если вместо этого вы переводите в новое положение и затем вращаетесь, ваша модель будет вращаться, как если бы она вращалась вокруг начала координат. Это, вероятно, не то, что вы хотите.
Если вы изменяете фактические позиции вершин непосредственно вместо использования матриц преобразования, вы делаете это неправильно. Даже если у вас есть только квадрат, оставьте координаты на (-1,-1) (-1,1) (1,1) (1,-1) (обратите внимание, как центр находится на (0,0)) и переведите их туда, где вы хотите быть.
Ты ... не нужно повторно реализовывать математические функции и, вероятно, не следует (если только ваша цель явно не заключается в этом). GLM-это популярная математическая библиотека, которая делает все, что вы хотите, и она специально разработана для OpenGL.
Окончательное Редактирование
Вот прекрасное произведение искусства, которое я нарисовал для вас, демонстрирующее, что вам нужно сделать.
Обратите внимание, как в правом нижнем углу модель была сметена вокруг начала координат мира примерно на 45 градусов. Если мы пошли еще на 45, у него был бы нижний край, параллельный оси X и пересекающий положительную ось Y с синей вершиной в левом нижнем углу и фиолетовой вершиной в правом нижнем углу.
Вероятно, вам следует изучить, как работать с вершинами, матрицами и шейдерами. Вершины должны быть заданы один раз , матрицы должны обновляться каждый раз, когда вы случайно меняете масштаб, поворот или положение объекта, а шейдеры должны умножать каждую вершину в модели на равномерное (постоянное).
Вашему спрайту не хватает достаточной информации, чтобы сделать то, что вы пытаетесь сделать. Чтобы вычислить вращение вокруг точки, вам нужно знать, что это за точка. А ты нет.
Поэтому, если вы хотите вращаться вокруг произвольного местоположения, вам нужно будет передать это местоположение шейдеру. Оказавшись там, вы вычитаете его из ваших позиций, поворачиваете позицию и добавляете ее обратно. Однако для этого потребуется много работы, поэтому вы должны просто вычислить матрицу на процессор, чтобы сделать все это. Ваш шейдер получит эту матрицу и выполнит само преобразование.
Конечно, это само по себе требует чего-то еще, потому что вы продолжаете обновлять положение этих объектов, смещая вершины на процессоре. это нехорошо; вы должны хранить эти объекты относительно их происхождения в буфере. Затем вы должны преобразовать их в их мировое положение как часть их матрицы.
Таким образом, ваш шейдер должен принимать объект-относительный координаты, и она должна быть передана матрице, которая делает поворот с последующим переводом их в положение мирового пространства. На самом деле, поскребите это; матрица должна преобразоваться в их конечное положение камеры-пространства (мировое пространство-всегда плохая идея).