0

在考虑 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();
   }

但是我不使用四元数的这种方法效果很好:

  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();

   }
4

2 回答 2

1

四元数仅描述旋转。结果,您想如何仅使用四元数围绕枢轴点旋转某些东西?

您需要的最小值是一个 R3 向量和一个四元数。只有一个级别的转换,您首先旋转对象,然后将其移动到那里。

如果您想创建一个矩阵,您首先创建配给矩阵,然后添加未更改的平移。

如果您只想调用 glTranslate 和 glRotate(或 glMultMatrix),您将首先调用 glTranslate,然后调用 glRoatate。

编辑:

如果您不进行渲染并且只想知道每个顶点的位置:

Vector3 newVertex = quat.transform(oldVertex) + translation;
于 2012-10-17T12:55:52.607 回答
1

在我看来,您已经考虑了旋转前后的来回平移。为什么最后调用 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)。对于相同的旋转,它们应该是相同的。

于 2012-10-18T08:37:09.973 回答