Opengl LWJGL 3-绕错误轴旋转的模型

Opengl LWJGL 3-绕错误轴旋转的模型,opengl,matrix,rotation,lwjgl,Opengl,Matrix,Rotation,Lwjgl,我的3D模型绕着错误的轴旋转。除了X轴以外,其他一切都可以工作。当我将Y和Z的角度设置为0时,X可以正常工作,但如果绕Z轴旋转90度,然后绕X旋转,它也会绕Z旋转。所以当使用Y或Z时,X会绕Z旋转。所以如果我让我的模型绕Z旋转90度,绕X旋转-90度,它会保持完全静止 变换矩阵的函数。如果我移动matrix.translate(位置)在旋转下,我的模型以一个巨大的圆圈旋转(可能围绕世界原点) 将矩阵转换为floatbuffer,以便将其传递给着色器: public static FloatBuf

我的3D模型绕着错误的轴旋转。除了X轴以外,其他一切都可以工作。当我将Y和Z的角度设置为0时,X可以正常工作,但如果绕Z轴旋转90度,然后绕X旋转,它也会绕Z旋转。所以当使用Y或Z时,X会绕Z旋转。所以如果我让我的模型绕Z旋转90度,绕X旋转-90度,它会保持完全静止

变换矩阵的函数。如果我移动
matrix.translate(位置)在旋转下,我的模型以一个巨大的圆圈旋转(可能围绕世界原点)

将矩阵转换为floatbuffer,以便将其传递给着色器:

public static FloatBuffer toFloatBuffer(Matrix4f matrix) {

    FloatBuffer buffer = BufferUtils.createFloatBuffer(16);

    buffer.put(matrix.m00());
    buffer.put(matrix.m01());
    buffer.put(matrix.m02());
    buffer.put(matrix.m03());
    buffer.put(matrix.m10());
    buffer.put(matrix.m11());
    buffer.put(matrix.m12());
    buffer.put(matrix.m13());
    buffer.put(matrix.m20());
    buffer.put(matrix.m21());
    buffer.put(matrix.m22());
    buffer.put(matrix.m23());
    buffer.put(matrix.m30());
    buffer.put(matrix.m31());
    buffer.put(matrix.m32());
    buffer.put(matrix.m33());

    buffer.flip();

    return buffer;
}
着色器中的用法:

gl_Position = transformationMatrix * vec4(position, 1.0) * viewMatrix * projectionMatrix;

模型的零点已设置为原点,我确信发送到这些函数的所有数据都是正确的。我已经调试了一段时间了。我正在使用LWJGL 3。

我认为您正面临着挑战。 这意味着,旋转的顺序很重要,然后你可能会得到奇怪的结果,比如你经历过的结果

要解决此问题,您必须使用

基本上,您必须:

  • 创建旋转四元数并将其与其他旋转四元数相乘
  • 必须创建表示X轴旋转的旋转四元数,以此类推,表示Y轴和Z轴的旋转四元数

  • 你把它们放大

  • 最后,您必须将生成的四元数转换为矩阵

在这里读到什么

编辑:

阅读此处有关如何将四元数转换为矩阵的内容:

这是我的Camera类(不幸的是,它使用四元数之类的JOGL库,但应该可以移植到LWJGL。它以Euler或四元数的方式提供围绕中心的缩放、移动和旋转,以及检索指向方向等方法

public class Camera {
    public Matrix4 matrix;
    public Quaternion rotation;
    public Vector3 position;
    public Vector3 scale;
    public Vector3 center;
    public Vector2 frictionx;
    public Vector2 frictiony;
    public Vector2 frictionz;
    public Camera() {
        matrix=new Matrix4();
        rotation=new Quaternion();
        position=new Vector3(0f,0f,0f);
        scale=new Vector3(1f,1f,1f);
        center=new Vector3(0f,0f,0f);
        frictionx=new Vector2(0,0);
        frictiony=new Vector2(0,0);
        frictionz=new Vector2(0,0);
    }
    public float tryFric(float a, float b) {
        try {
            float r=a/b;
            if (r == Float.NaN) {
                return 0;
            }
            return r;
        }
        catch (Exception e) {
            return 0;
        }
    }
    public void getFrictions(Vector3 pointing) {
        frictionx.x=tryFric(pointing.y,pointing.x);
        frictionx.y=tryFric(pointing.z,pointing.x);
        frictiony.x=tryFric(pointing.x,pointing.y);
        frictiony.y=tryFric(pointing.z,pointing.y);
        frictionz.x=tryFric(pointing.x,pointing.z);
        frictionz.y=tryFric(pointing.y,pointing.z);
    }
    public Vector3 getPointing(Vector3 vec) {
        float[] in=new float[] {vec.x,vec.y,vec.z};
        float[] out=new float[3];
        rotation.conjugate();
        rotation.rotateVector(out, 0, in, 0);
        rotation.conjugate();
        Vector3 p=new Vector3(out[0],out[1],out[2]);
        getFrictions(p);
        return p;
    }
    public void move(float x, float y, float z) {
        position.x+=x;
        position.y+=y;
        position.z+=z;
    }
    public void setPosition(float x, float y, float z) {
        position.x=x;
        position.y=y;
        position.z=z;
    }
    public void moveCenter(float x, float y, float z) {
        center.x+=x;
        center.y+=y;
        center.z+=z;
    }
    public void setCenter(float x, float y, float z) {
        center.x=x;
        center.y=y;
        center.z=z;
    }
    public void scale(float x, float y, float z) {
        scale.x*=x;
        scale.y*=y;
        scale.z*=z;
    }
    public void setScale(float x, float y, float z) {
        scale.x=x;
        scale.y=y;
        scale.z=z;
    }
    public void rotateQuaternion(float angle, float x, float y, float z) {
        Quaternion rotationy=new Quaternion();
        rotationy.rotateByAngleY(angle*y);
        rotation.mult(rotationy);
        Quaternion rotationx=new Quaternion();
        rotationx.rotateByAngleX(angle*x);
        rotation.mult(rotationx);
        Quaternion rotationz=new Quaternion();
        rotationz.rotateByAngleZ(angle*z);
        rotation.mult(rotationz);
        rotation.normalize();
    }
    public void rotateEuler(float angle, float x, float y, float z) {
        rotation.rotateByEuler(angle*x, angle*y, angle*z);
    }
    public Vector3 getPointing() {
        Matrix4 as_matrix=new Matrix4();
        as_matrix.loadIdentity();
        as_matrix.rotate(rotation);
        float[] out=new float[3];
        float[] in=new float[] {0,0,-1};
        as_matrix.multVec(in, out);
        Vector3 pointing=new Vector3(out[0],out[1],out[2]);
        return pointing;
    }
    public Matrix4 getMatrix() {
        Matrix4 rot_as_mat=new Matrix4();
        rot_as_mat.loadIdentity();
        rot_as_mat.translate(center.x, center.y, center.z);
        rot_as_mat.rotate(rotation);
        Matrix4 result=new Matrix4();
        result.loadIdentity();
        result.scale(scale.x, scale.y, scale.z);
        result.multMatrix(rot_as_mat);
        result.translate(position.x,position.y,position.z);
        matrix=result;
        return result;
    }
}
希望有帮助

注:

  • 您可能需要尝试旋转四元数乘法顺序以获得不同的结果

    • 我想你正面临着挑战。 这意味着,旋转的顺序很重要,然后你可能会得到奇怪的结果,比如你经历过的结果

      要解决此问题,您必须使用

      基本上,您必须:

      • 创建旋转四元数并将其与其他旋转四元数相乘
      • 必须创建表示X轴旋转的旋转四元数,以此类推,表示Y轴和Z轴的旋转四元数

      • 你把它们放大

      • 最后,您必须将生成的四元数转换为矩阵

      在这里读到什么

      编辑:

      阅读此处有关如何将四元数转换为矩阵的内容:

      这是我的Camera类(不幸的是,它使用四元数之类的JOGL库,但应该可以移植到LWJGL。它以Euler或四元数的方式提供围绕中心的缩放、移动和旋转,以及检索指向方向等方法

      public class Camera {
          public Matrix4 matrix;
          public Quaternion rotation;
          public Vector3 position;
          public Vector3 scale;
          public Vector3 center;
          public Vector2 frictionx;
          public Vector2 frictiony;
          public Vector2 frictionz;
          public Camera() {
              matrix=new Matrix4();
              rotation=new Quaternion();
              position=new Vector3(0f,0f,0f);
              scale=new Vector3(1f,1f,1f);
              center=new Vector3(0f,0f,0f);
              frictionx=new Vector2(0,0);
              frictiony=new Vector2(0,0);
              frictionz=new Vector2(0,0);
          }
          public float tryFric(float a, float b) {
              try {
                  float r=a/b;
                  if (r == Float.NaN) {
                      return 0;
                  }
                  return r;
              }
              catch (Exception e) {
                  return 0;
              }
          }
          public void getFrictions(Vector3 pointing) {
              frictionx.x=tryFric(pointing.y,pointing.x);
              frictionx.y=tryFric(pointing.z,pointing.x);
              frictiony.x=tryFric(pointing.x,pointing.y);
              frictiony.y=tryFric(pointing.z,pointing.y);
              frictionz.x=tryFric(pointing.x,pointing.z);
              frictionz.y=tryFric(pointing.y,pointing.z);
          }
          public Vector3 getPointing(Vector3 vec) {
              float[] in=new float[] {vec.x,vec.y,vec.z};
              float[] out=new float[3];
              rotation.conjugate();
              rotation.rotateVector(out, 0, in, 0);
              rotation.conjugate();
              Vector3 p=new Vector3(out[0],out[1],out[2]);
              getFrictions(p);
              return p;
          }
          public void move(float x, float y, float z) {
              position.x+=x;
              position.y+=y;
              position.z+=z;
          }
          public void setPosition(float x, float y, float z) {
              position.x=x;
              position.y=y;
              position.z=z;
          }
          public void moveCenter(float x, float y, float z) {
              center.x+=x;
              center.y+=y;
              center.z+=z;
          }
          public void setCenter(float x, float y, float z) {
              center.x=x;
              center.y=y;
              center.z=z;
          }
          public void scale(float x, float y, float z) {
              scale.x*=x;
              scale.y*=y;
              scale.z*=z;
          }
          public void setScale(float x, float y, float z) {
              scale.x=x;
              scale.y=y;
              scale.z=z;
          }
          public void rotateQuaternion(float angle, float x, float y, float z) {
              Quaternion rotationy=new Quaternion();
              rotationy.rotateByAngleY(angle*y);
              rotation.mult(rotationy);
              Quaternion rotationx=new Quaternion();
              rotationx.rotateByAngleX(angle*x);
              rotation.mult(rotationx);
              Quaternion rotationz=new Quaternion();
              rotationz.rotateByAngleZ(angle*z);
              rotation.mult(rotationz);
              rotation.normalize();
          }
          public void rotateEuler(float angle, float x, float y, float z) {
              rotation.rotateByEuler(angle*x, angle*y, angle*z);
          }
          public Vector3 getPointing() {
              Matrix4 as_matrix=new Matrix4();
              as_matrix.loadIdentity();
              as_matrix.rotate(rotation);
              float[] out=new float[3];
              float[] in=new float[] {0,0,-1};
              as_matrix.multVec(in, out);
              Vector3 pointing=new Vector3(out[0],out[1],out[2]);
              return pointing;
          }
          public Matrix4 getMatrix() {
              Matrix4 rot_as_mat=new Matrix4();
              rot_as_mat.loadIdentity();
              rot_as_mat.translate(center.x, center.y, center.z);
              rot_as_mat.rotate(rotation);
              Matrix4 result=new Matrix4();
              result.loadIdentity();
              result.scale(scale.x, scale.y, scale.z);
              result.multMatrix(rot_as_mat);
              result.translate(position.x,position.y,position.z);
              matrix=result;
              return result;
          }
      }
      
      希望有帮助

      注:

      • 您可能需要尝试旋转四元数乘法顺序以获得不同的结果


      如果组合旋转,则在第一次平移后,将在坐标系中应用第二次旋转。例如:如果围绕X旋转90度,则随后局部Y轴将指向全局Z轴,依此类推。不相关,但着色器中的变换顺序看起来是错误的。除非视图和投影被转置,否则它将被禁用oE从右边将它们相乘是没有意义的。@rabbi76这仍然不能解决我的问题–@rabbi76我真的不知道你的意思,但你不能看看上面的代码。输入向量旋转只包含度(0-360)。我想这是有人回答的万向节锁,因为Y旋转输入是90。我只是不知道如何修复它。@rabbi76好吧,必须有一些其他人使用的解决方案如果你组合旋转,那么第二个旋转在第一次平移后应用于坐标系中。例如:如果你围绕X旋转90度,然后t局部Y轴指向全局Z轴等等。不相关,但着色器中的变换顺序看起来是错误的。除非视图和投影被转置,否则从右侧将它们相乘是没有意义的。@rabbi76这仍然不能解决我的问题–@rabbi76我真的不知道你的意思,但你能不能只看一下它上面的e代码。输入向量旋转仅包含度(0-360).我想这是有人回答的万向节锁,因为Y旋转输入是90。我只是不知道如何修复它。@rabbi76嗯,必须有一些其他人使用的解决方案。我仍然看不出有什么不同。。我应该如何将得到的四元数转换成矩阵?@Maineri:看看这个:@user7185317仍然不起作用。。可以吗我只使用四元数rotationx.rotateX(xRotInRadians)等等,或者我应该如何创建旋转四元数?@Maineri:是的,应该是这样。不幸的是,我正在使用jogl,但我会在我的帖子中粘贴相关代码。我很难理解这一点。摩擦在这里意味着什么?我如何用这个最简单的方法旋转我的模型矩阵?调用什么函数?像那样ler.我应该给它什么作为输入呢?我仍然看不出有什么区别..我应该如何将得到的四元数转换成矩阵?@Maineri:看看这个:@user7185317仍然不起作用..我可以用四元数rotationx.rotateX(xRotInRadians)吗等等,或者我应该如何创建旋转四元数?@Maineri:是的,应该是这样。不幸的是,我正在使用jogl,但我会在我的帖子中粘贴相关代码。我很难理解这一点。摩擦在这里意味着什么?我如何用这个最简单的方法旋转我的模型矩阵?调用什么函数?像那样我应该给它什么作为输入?