Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

opengl object vibrate after moving a distance

I have an object which moves on a terrain and a third person camera follow it, after I move it for some distance in different directions it begin to shaking or vibrating even if it is not moving and the camera rotates around it, this is the moving code of the object

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

and the camera rotation is

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);
}
like image 377
Mohamed Mousa El-Kheshen Avatar asked Oct 04 '17 13:10

Mohamed Mousa El-Kheshen


2 Answers

  1. float is sometimes not enough.

    I use double precision matrices on CPU side to avoid such problems. But as you are on Android it might not be possible. For GPU use floats again as there are no 64bit interpolators yet.

  2. Big numbers are usually the problem

    If your world is big then you are passing big numbers into the equations multiplying any errors and only at the final stage the stuff is translated relative to camera position meaning the errors stay multiplied but the numbers got clamped so error/data ratio got big.

    To lower this problem before rendering convert all vertexes to coordinate system with origin at or near your camera. You can ignore rotations just offset the positions.

    This way you will got higher errors only far away from camera which is with perspective not visible anyway... For more info see:

    • ray and ellipsoid intersection accuracy improvement
  3. Use cumulative transform matrix instead of Euler angles

    for more info see Understanding 4x4 homogenous transform matrices and all the links at bottom of that answer.

like image 124
Spektre Avatar answered Nov 16 '22 23:11

Spektre


This sounds like a numerical effect to me. Even small offsets coming from your game object will influence the rotation of the following camera with small movements / rotations and it looks like a vibrating object / camera.

So what you can do is:

  • Check if the movement above a threshold value before calculating a new rotation for your camera
  • When you are above this threshold: do a linear interpolation between the old and the new rotation using the lerp-algorithm for the quaternion ( see this unity answer to get a better understanding how your code can look like: Unity lerp discussion )
like image 36
KimKulling Avatar answered Nov 17 '22 00:11

KimKulling