5

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

2 Answers2

3

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 )
KimKulling
  • 2,654
  • 1
  • 15
  • 26
  • 1
    I made a linear interpolation for the camera rotation `xoffset = glm::mix(xoffset, nx,(GLfloat) delta);` but didn't solve the problem, the object itself which is vibrating not the camera and I move it by adding `glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f));` to its direction vector so could I make linear interpolation for that translation vector if yes with what? – Mohamed Mousa El-Kheshen Oct 04 '17 at 14:59
  • 1
    From old position to new position I guess. – KimKulling Oct 04 '17 at 15:01
  • 1
    I changed the code to the following `glm::vec3 opos = getPosition(); glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f)); glm::mat4 nmat(matrix); nmat = glm::translate(matrix, t); glm::vec3 npos(nmat[3]); glm::vec3 ipos = glm::mix(npos, opos, (GLfloat) delta); matrix[3] = glm::vec4(ipos, 1.0f); glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); f = -glm::normalize(f) * (velocity * 3.0f); camera->translate(f);` I get the old position and apply the translation to a temporary matrix then get the position and make interpolation using glm::mix but not solved – Mohamed Mousa El-Kheshen Oct 04 '17 at 15:18
  • 1
    the problem was in the shader precision was medium when I set it to high the vibration hidden, with interpolation the result become very good, thank you – Mohamed Mousa El-Kheshen Oct 16 '17 at 12:02
3
  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:

  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.

Spektre
  • 49,595
  • 11
  • 110
  • 380