当前位置: 首页 > 知识库问答 >
问题:

实现六自由度滚动的几个问题

池俊茂
2023-03-14

我使用的相机有偏航、俯仰和滚动。当偏航==0时,相机向下看-z轴(偏航==90是正x),当俯仰==270时,相机向上看(俯仰==0是直视),当滚动==180时,相机倒置。

相机的偏航、俯仰和滚动值永远不会小于零或大于360(当任何值接近0或360时,当它通过该量时,它会自动移动到“另一侧”)。

我已经实现了3DoF,它运行得很好;然而,当我实现6DoF时,在滚动大约为90或270之前,一切似乎都在工作,然后向上和向右的向量发生奇怪的事情(向前似乎总是工作的,因为滚动围绕该轴旋转?)

我渲染的场景只是一堆块(在minecraft风格的块中),我总是能够向前/向后移动,并使用前向向量来瞄准一个块,这样我就知道前向向量已经完成。

这是我的initGL:

public void initGL() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glShadeModel(GL11.GL_SMOOTH);
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    GL11.glClearDepth(1.0);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthFunc(GL11.GL_LEQUAL);

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();

    GLU.gluPerspective(fov, ((float) Display.getWidth()) / ((float) Display.getHeight() != 0 ? Display.getHeight() : 1), 0.1f, 100.0f);//fov is 45.0f

    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
}

这里是我旋转并转换到相机视图的地方:

public final void lookThrough() {
    GL11.glRotatef(this.roll, 0.0f, 0.0f, 1.0f);
    GL11.glRotatef(this.pitch, 1.0f, 0.0f, 0.0f);
    GL11.glRotatef(this.yaw, 0.0f, 1.0f, 0.0f);
    GL11.glTranslatef(-this.position.x, -this.position.y, -this.position.z);
}

以下是我的六自由度计算:

public static final double  zeroRad         = Math.toRadians(0);
public static final double  ninetyRad       = Math.toRadians(90);
public static final double  oneEightyRad    = Math.toRadians(180);
public static final double  twoSeventyRad   = Math.toRadians(270);

public static final strictfp void updateLookVectorsIn6DoF(Vector3f yawPitchAndRoll, Vector3f forward, Vector3f up, Vector3f right) {
    final double yaw = Math.toRadians(yawPitchAndRoll.getX());
    final double pitch = Math.toRadians(yawPitchAndRoll.getY());
    final double roll = Math.toRadians(yawPitchAndRoll.getZ());

    final float sinYaw = ((float) Math.sin(yaw));
    final float cosYaw = ((float) Math.cos(yaw));

    final float sinYaw90 = ((float) Math.sin(yaw + ninetyRad));
    //final float sinYaw180 = ((float) Math.sin(yaw + oneEightyRad));
    final float cosYaw270 = ((float) Math.cos(yaw - ninetyRad));

    final float sinRoll = ((float) Math.sin(roll));
    final float cosRoll = ((float) Math.cos(roll));
    //final float sinRoll180 = ((float) Math.sin(roll + oneEightyRad));

    final float cosPitch90 = ((float) Math.cos(pitch + ninetyRad));
    //final float cosPitch270 = ((float) Math.cos(pitch + twoSeventyRad));
    final float sinPitch90 = ((float) Math.sin(pitch + ninetyRad));
    final float sinPitch270 = ((float) Math.sin(pitch - ninetyRad));

    //Forward:(No roll because roll goes around the Z axis and forward movement is in that axis.)
    float x = sinYaw * ((float) Math.cos(pitch));
    float y = -((float) Math.sin(pitch));
    float z = cosYaw * ((float) Math.cos(pitch - oneEightyRad));
    forward.set(x, y, z);

    //cos(90) = 0, cos(180) = -1, cos(270) = 0, cos(0) = 1
    //sin(90) = 1, sin(180) = 0, sin(270) = -1, sin(0) = 0

    //Up: Strange things occur when roll is near 90 or 270 and yaw is near 0 or 180
    x = -(sinYaw * cosPitch90) * cosRoll - (sinRoll * sinYaw90);
    y = -sinPitch270 * cosRoll;
    z = (cosYaw * cosPitch90) * cosRoll + (sinRoll * cosYaw270);
    up.set(x, y, z);
    //Right: Strange things occur when roll is near 90 or 270 and pitch is near 90 or 270
    x = (cosRoll * sinYaw90) - (sinRoll * (sinYaw * cosPitch90));
    y = 0 - (sinRoll * sinPitch90);//This axis works fine
    z = (cosRoll * cosYaw270) + (sinRoll * (sinYaw * cosPitch90));
    right.set(x, y, z);
}

我确实在这里发现了一个非常类似的问题,但它使用了矩阵和四元数,我不想这样做,除非我绝对必须这样做(我小心地尝试以正确的顺序乘以横摇和横摇):LWJGL-在使用四元数和平移矩阵的六自由度相机中实现“滚动”的问题

共有1个答案

司徒墨竹
2023-03-14

所以我终于掌握了cos和sin的含义(但不要让我教它),并且能够让它发挥作用!

以下是经过改进的新代码:

public static final double  zeroRad         = Math.toRadians(0);
public static final double  ninetyRad       = Math.toRadians(90);
public static final double  oneEightyRad    = Math.toRadians(180);
public static final double  twoSeventyRad   = Math.toRadians(270);

public static final strictfp void updateLookVectorsIn6DoF(Vector3f yawPitchAndRoll, Vector3f forward, Vector3f up, Vector3f right) {
    final double yaw = Math.toRadians(yawPitchAndRoll.getX());
    final double pitch = Math.toRadians(yawPitchAndRoll.getY());
    final double roll = Math.toRadians(yawPitchAndRoll.getZ());

    final float sinYaw = ((float) Math.sin(yaw));
    final float cosYaw = ((float) Math.cos(yaw));

    final float sinYaw90 = ((float) Math.sin(yaw + ninetyRad));
    final float sinYaw270 = ((float) Math.sin(yaw - ninetyRad));//+ twoSeventyRad));
    final float cosYaw90 = ((float) Math.cos(yaw + ninetyRad));
    final float cosYaw180 = ((float) Math.cos(yaw + oneEightyRad));
    final float cosYaw270 = ((float) Math.cos(yaw - ninetyRad));//+ twoSeventyRad));

    final float sinRoll = ((float) Math.sin(roll));
    final float cosRoll = ((float) Math.cos(roll));
    final float cosRoll180 = ((float) Math.cos(roll + oneEightyRad));

    final float cosPitch90 = ((float) Math.cos(pitch + ninetyRad));
    final float sinPitch90 = ((float) Math.sin(pitch + ninetyRad));
    final float sinPitch270 = ((float) Math.sin(pitch - ninetyRad));

    //Forward:(No roll because roll goes around the Z axis and forward movement is in that axis.)
    float x = sinYaw * ((float) Math.cos(pitch));
    float y = -((float) Math.sin(pitch));
    float z = cosYaw * ((float) Math.cos(pitch - oneEightyRad));
    forward.set(x, y, z);

    //Multiply in this order: roll, pitch, yaw
    //cos(90) = 0, cos(180) = -1, cos(270) = 0, cos(0) = 1
    //sin(90) = 1, sin(180) = 0, sin(270) = -1, sin(0) = 0

    //hmm... gimbal lock, eh? No!

    //Up://
    x = (cosRoll180 * cosPitch90 * sinYaw) - (sinRoll * cosYaw180);
    y = -sinPitch270 * cosRoll;
    z = (cosRoll * cosPitch90 * cosYaw) + (sinRoll * sinYaw);
    up.set(x, y, z);
    //Right:
    x = (cosRoll * sinYaw90) - (sinRoll * cosPitch90 * cosYaw90);
    y = 0 - (sinRoll * sinPitch90);//This axis works fine
    z = (cosRoll * cosYaw270) + (sinRoll * cosPitch90 * sinYaw270);
    right.set(x, y, z);
}
 类似资料:
  • 本文向大家介绍Android简单实现无限滚动自动滚动的ViewPager,包括了Android简单实现无限滚动自动滚动的ViewPager的使用技巧和注意事项,需要的朋友参考一下 经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的ViewPager 效果如下: 简

  • 本文向大家介绍JS JQUERY实现滚动条自动滚到底的方法,包括了JS JQUERY实现滚动条自动滚到底的方法的使用技巧和注意事项,需要的朋友参考一下 设置页面加载时滚动条自动滚到底的方法: jQuery: JavaScript: 以上2种方法均可以实现页面加载时滚动条自动滚动到底,小伙伴们根据自己的实际需求,自由选择吧

  • 本文向大家介绍js实现滚动条滚动到某个位置便自动定位某个tr,包括了js实现滚动条滚动到某个位置便自动定位某个tr的使用技巧和注意事项,需要的朋友参考一下 要实现带滚动条的table,定位到某个tr,其实是很简单的,只有几行js代码就可以完成,具体内容如下 js代码 html 效果图: 虽说是几行代码,但要彻底弄懂。要熟悉animate的使用,scrollTop,.offsetTop的意思方可得心

  • 我正在尝试在Android中实现一个自定义线性布局管理器。用于获得水平自动滑动的RecolyerView。但是当我试图将自定义类调用到主java类中时,我会遇到一些问题。 下面列出了我的代码所面临的问题。 请告诉上述错误的解决方法。另外,请精确的代码,以实现水平自动滑动回收视图。使用我已经提到的自定义线性布局管理器。

  • 本文向大家介绍android实现歌词自动滚动效果,包括了android实现歌词自动滚动效果的使用技巧和注意事项,需要的朋友参考一下 最近在做Android 的MP3播放的项目,要实现歌词的自动滚动,以及同步显示。 lyric的歌词解析主要用yoyoplayer里面的,显示部分参考了这里 ,这里只是模拟MP3歌词的滚动。 先上一下效果图: 滚动实现的代码其实也简单。显示画出当前时间点的歌词,然后再分

  • 本文向大家介绍linux实现自动删除最旧的几个文件详解,包括了linux实现自动删除最旧的几个文件详解的使用技巧和注意事项,需要的朋友参考一下 前言 因为公司的文件服务器上存有所需的项目war包,一段时间以后,大量不用的工程文件占用磁盘空间,需要定期删除无用的文件。这些文件归属不同的项目目录下,创建的时间各不相同。某些陈旧项目已经数年没有更新。因此,不能只定期删除某个目录下的文件,更不能按时间删除