Локальное вращение в указанных c реализациях openGL и LWJGL - PullRequest
0 голосов
/ 13 января 2020

Я также занимаюсь проблемой глобальной / локальной ротации и не могу ее решить. Для реализации моей игры я использовал книгу lwjgl , используя openGL и LWJGL. Я использую библиотеку JOML для векторов и матриц.

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

public Matrix4f getModelViewMatrix(Object obj, Matrix4f viewMatrix) {
    Vector3f rotation = obj.getRot();
    Vector3f localRot = obj.getLocalRot();

    Matrix4f localRotMat = new Matrix4f().identity();
    Matrix4f worldRotMat = new Matrix4f().identity();

    localRotMat.rotateLocalX((float)Math.toRadians(localRot.x)).
                rotateLocalY((float)Math.toRadians(localRot.y)).
                rotateLocalZ((float)Math.toRadians(localRot.z));

    worldRotMat.rotateX((float)Math.toRadians(-rotation.x)).
                rotateY((float)Math.toRadians(-rotation.y)).
                rotateZ((float)Math.toRadians(-rotation.z));

    modelViewMatrix.identity().translate(obj.getPos());

    modelViewMatrix.mulLocal(localRotMat);
    modelViewMatrix.mul(worldRotMat);

    modelViewMatrix.scale(obj.getScale());
    Matrix4f viewCurr = new Matrix4f(viewMatrix);
    return viewCurr.mul(modelViewMatrix);
}

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

Соответствующий код для класса объекта:

// Object class
private final Vector3f rot;

private final Vector3f localRot;

public Object() {
    pos = new Vector3f(0, 0, 0);
    scale = 1;
    rot = new Vector3f(0, 0, 0);
    localRot = new Vector3f(0, 0, 0);
}

// getters and setters for above

Может кто-нибудь объяснить, что не так с расчетом поворотов для матрицы вида модели?

РЕДАКТИРОВАТЬ: я могу переписать код, как показано ниже, что немного больше соответствует советам @GeestWagen. Тем не менее, «локальное вращение» моего объекта по-прежнему отображается как глобальное, поэтому действительно кажется, что оно применено «одинаковое» вращение дважды. Однако теперь я застрял, потому что не могу найти больше документации по этим функциям (rotateLocal / rotate).

modelViewMatrix.identity().translate(obj.getPos()).
                rotateLocalX((float)Math.toRadians(-localRot.x)).
                rotateLocalY((float)Math.toRadians(-localRot.y)).
                rotateLocalZ((float)Math.toRadians(-localRot.z)).
                rotateX((float)Math.toRadians(-rotation.x)).
                rotateY((float)Math.toRadians(-rotation.y)).
                rotateZ((float)Math.toRadians(-rotation.z)).
                scale(obj.getScale());

1 Ответ

0 голосов
/ 14 января 2020

Хорошо, я наконец исправил это. Это привело ко мне больше исследований. Я придумал следующее:

Vector3f rotation = obj.getRot();
Vector3f localRot = obj.getLocalRot();

Quaternionf rotationQ = new Quaternionf().
        rotateAxis((float)Math.toRadians(-localRot.z), new Vector3f(0f, 0f, 1f)).
        rotateAxis((float)Math.toRadians(-localRot.y), new Vector3f(0f, 1f, 0f)).
        rotateAxis((float)Math.toRadians(-localRot.x), new Vector3f(1f, 0f, 0f)).
    premul(new Quaternionf().
        rotateX((float)Math.toRadians(-rotation.x)).
        rotateY((float)Math.toRadians(-rotation.y)).
        rotateZ((float)Math.toRadians(-rotation.z))
    );

modelViewMatrix.identity().
    translate(obj.getPos()).
    rotate(rotationQ).
    scale(obj.getScale());

Это вдохновлено, среди прочего, этим и этим . Что меня смутило, так это отсутствие хитов при выполнении локальных и глобальных вращений. Большинство вещей, которые я смог найти, было либо . Это создает кватернион и устанавливает оси x, y и z в локальное вращение объекта. Затем он предварительно умножает на кватернион, оси которого установлены на глобальное вращение объекта. Затем этот результирующий кватернион используется для матрицы modelView.

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

...