opengl对象在移动一段距离后振动

时间:2017-10-04 13:32:33

标签: android c++ opengl-es

我有一个在地形上移动的物体,第三人称相机跟随它,在我向不同方向移动一段距离后,即使它没有移动并且相机围绕它旋转,它也开始摇晃或振动,这个是对象的移动代码

double& delta = engine.getDeltaTime();
GLfloat velocity = delta * movementSpeed;
glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f));
//translate the objet atri before rendering
matrix = glm::translate(matrix, t);
//get the forward vetor of the matrix
glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]);
f = glm::normalize(f);
f = f * (velocity * 3.0f);
f = -f;
camera.translate(f);

并且相机旋转

void Camera::rotate(GLfloat xoffset, GLfloat yoffset, glm::vec3& c, double& delta, GLboolean constrainpitch) {
    xoffset *= (delta * this->rotSpeed);
    yoffset *= (delta * this->rotSpeed);
    pitch += yoffset;
    yaw += xoffset;
    if (constrainpitch) {
        if (pitch >= maxPitch) {
            pitch = maxPitch;
            yoffset = 0;
        }
        if (pitch <= minPitch) {
            pitch = minPitch;
            yoffset = 0;
        }
    }
    glm::quat Qx(glm::angleAxis(glm::radians(yoffset), glm::vec3(1.0f, 0.0f, 0.0f)));
    glm::quat Qy(glm::angleAxis(glm::radians(xoffset), glm::vec3(0.0f, 1.0f, 0.0f)));
    glm::mat4 rotX = glm::mat4_cast(Qx);
    glm::mat4 rotY = glm::mat4_cast(Qy);
    view = glm::translate(view, c);
    view = rotX * view;
    view = view * rotY;
    view = glm::translate(view, -c);
}

2 个答案:

答案 0 :(得分:3)

这听起来像是对我的数字效果。即使是来自游戏对象的小偏移也会影响后续摄像机的旋转,并且运动/旋转很小,看起来像是一个振动的物体/摄像机。

所以你可以做的是:

  • 在计算相机的新旋转之前检查移动是否超过阈值
  • 当您超过此阈值时:使用针对四元数的lerp算法在旧旋转和新旋转之间进行线性插值(请参阅此统一答案以更好地了解代码的外观:{{3} })

答案 1 :(得分:2)

  1. float有时不够。

    我在 CPU 端使用double精度矩阵来避免此类问题。但是,当您使用 Android 时,可能无法实现。对于 GPU 再次使用float,因为还没有64位插值器。

  2. 大数字通常是问题

    如果你的世界很大,那么你将大数字传递给方程式乘以任何误差,并且只在最后阶段相对于摄像机位置翻译东西意味着错误保持成倍但数字被钳制以便得到错误/数据比率大。

    要降低此问题,请先将所有顶点转换为相机处或附近的原点坐标系。您可以忽略旋转,只是偏移位置。

    通过这种方式,您将获得更高的错误,远离相机,无论如何都无法看到透视...有关详细信息,请参阅:

  3. 使用累积变换矩阵代替欧拉角

    有关详细信息,请参阅Understanding 4x4 homogenous transform matrices以及该答案底部的所有链接。