Вращение на основе кватернионов и положение поворота

Я не могу понять, как выполнить поворот матрицы с помощью Quaternion с учетом положения поворота в OpenGL. В настоящее время я получаю поворот объекта вокруг некоторой точки в пространстве, а не локальный поворот, который я хочу. Вот код [с использованием Java]

Метод вращения кватерниона:

  public void rotateTo3(float xr, float yr, float zr) {

    _rotation.x = xr;
    _rotation.y = yr;
    _rotation.z = zr;

    Quaternion xrotQ = Glm.angleAxis((xr), Vec3.X_AXIS);
    Quaternion yrotQ = Glm.angleAxis((yr), Vec3.Y_AXIS);
    Quaternion zrotQ = Glm.angleAxis((zr), Vec3.Z_AXIS);
    xrotQ = Glm.normalize(xrotQ);
    yrotQ = Glm.normalize(yrotQ);
    zrotQ = Glm.normalize(zrotQ);

    Quaternion acumQuat;
    acumQuat = Quaternion.mul(xrotQ, yrotQ);
    acumQuat = Quaternion.mul(acumQuat, zrotQ);



    Mat4 rotMat = Glm.matCast(acumQuat);

    _model = new Mat4(1);

   scaleTo(_scaleX, _scaleY, _scaleZ);

    _model = Glm.translate(_model, new Vec3(_pivot.x, _pivot.y, 0));

    _model =rotMat.mul(_model);//_model.mul(rotMat); //rotMat.mul(_model);

    _model = Glm.translate(_model, new Vec3(-_pivot.x, -_pivot.y, 0));


   translateTo(_x, _y, _z);

    notifyTranformChange();
   }

Метод масштабирования матрицы модели: public void scaleTo (float x, float y, float z) {

    _model.set(0, x);
    _model.set(5, y);
    _model.set(10, z);

    _scaleX = x;
    _scaleY = y;
    _scaleZ = z;

    notifyTranformChange();
  }

Метод перевода: public void translateTo (float x, float y, float z) {

    _x = x - _pivot.x;
    _y = y - _pivot.y;
    _z = z;
    _position.x = _x;
    _position.y = _y;
    _position.z = _z;

    _model.set(12, _x);
    _model.set(13, _y);
    _model.set(14, _z);

    notifyTranformChange();
   }

Но этот метод, в котором я не использую Quaternion, отлично работает:

  public void rotate(Vec3 axis, float angleDegr) {
    _rotation.add(axis.scale(angleDegr));
    //  change to GLM:
    Mat4 backTr = new Mat4(1.0f);

    backTr = Glm.translate(backTr, new Vec3(_pivot.x, _pivot.y, 0));

    backTr = Glm.rotate(backTr, angleDegr, axis);


    backTr = Glm.translate(backTr, new Vec3(-_pivot.x, -_pivot.y, 0));

    _model =_model.mul(backTr);///backTr.mul(_model);
    notifyTranformChange();

   }

person Michael IV    schedule 17.10.2012    source источник


Ответы (2)


Мне кажется, вы уже учитываете возвратно-поступательное движение до и после поворота. Почему этот последний вызов translateTo?

Кроме того, когда вы вращаете, всегда подразумевается чистое вращение вокруг начала координат. Итак, если вы хотите вращение вокруг своей точки поворота. Я бы хотел перевести вашу точку поворота в начало координат, затем повернуть, а затем перевести обратно в точку поворота, было бы правильным поступком. Поэтому я ожидал, что ваш код будет выглядеть так:

_model = Glm.translate(_model, new Vec3(-_pivot.x, -_pivot.y, 0));

_model =rotMat.mul(_model);//_model.mul(rotMat); //rotMat.mul(_model);

_model = Glm.translate(_model, new Vec3(_pivot.x, _pivot.y, 0));

и без звонка translateTo(_x, _y, _z);. Кроме того, можете ли вы подтвердить, что часть вращения уже выполняет то, что должна? Вы можете проверить это, сравнив rotMat с Glm.rotate(new Mat4(1.0f), angleDegr, axis). Они должны быть одинаковыми для одного вращения.

person ilmiacs    schedule 18.10.2012

Кватернион описывает только вращение. В результате, как вы хотите повернуть что-либо вокруг точки поворота, используя только кватернион?

Минимум, который вам понадобится, - это вектор R3 и кватернион. Имея только один уровень трансформации, вы сначала вращаете объект, а затем перемещаете его туда.

Если вы хотите создать матрицу, вы сначала создаете матрицу рационов, а затем добавляете перевод без изменений.

Если вы хотите просто вызвать glTranslate и glRotate (или glMultMatrix), вы должны сначала вызвать glTranslate, а затем glRoatate.

Редактировать:

Если вы не выполняете рендеринг и просто хотите знать, где находится каждая вершина:

Vector3 newVertex = quat.transform(oldVertex) + translation;
person rioki    schedule 17.10.2012
comment
Я знаю, что такое Quaternion, и фиксированный конвейер не использую :) - person Michael IV; 17.10.2012
comment
Но первое предложение решает вашу проблему, верно. Либо вы вычисляете матрицу преобразования, как я сказал, либо применяете кватернион и перенос к каждой вершине. - person rioki; 17.10.2012