Шейдер 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 2

2 ответа:

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

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

Итог: Вы должны вращаться, прежде чем переводить.

Вот типичный способ преобразования вершин:

OpenGL сторона:

  1. Вычислить матрицу ModelView: масштаб * вращение * перевод

  2. Переход к шейдеру в виде однородной матрицы

Сторона GLSL:

  1. Умножение вершин на матрицу ModelView в вершинном шейдере

  2. Отправить в gl_Position

Ответ на редактирование:

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

  • Если вы просто не переведете эти точки, а затем повернете их, автомобиль будет вращаться вокруг своего центра. Если вы переведете позже, автомобиль будет переведен в своем вращенном виде в указанное вами место. Ключ здесь в том, что начало вашей модели совпадает с началом вращения, так что вы в конечном итоге вращаете модель "вокруг себя."

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

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

  • Ты ... не нужно повторно реализовывать математические функции и, вероятно, не следует (если только ваша цель явно не заключается в этом). GLM-это популярная математическая библиотека, которая делает все, что вы хотите, и она специально разработана для OpenGL.

Окончательное Редактирование

Вот прекрасное произведение искусства, которое я нарисовал для вас, демонстрирующее, что вам нужно сделать.Введите описание изображения здесь
  • Обратите внимание, как в правом нижнем углу модель была сметена вокруг начала координат мира примерно на 45 градусов. Если мы пошли еще на 45, у него был бы нижний край, параллельный оси X и пересекающий положительную ось Y с синей вершиной в левом нижнем углу и фиолетовой вершиной в правом нижнем углу.

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

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

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

Конечно, это само по себе требует чего-то еще, потому что вы продолжаете обновлять положение этих объектов, смещая вершины на процессоре. это нехорошо; вы должны хранить эти объекты относительно их происхождения в буфере. Затем вы должны преобразовать их в их мировое положение как часть их матрицы.

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