Angle between two 3D vectors in degrees

Viewed 62

My goal is to rotate the enemies in my game to look towards my player. The code for it looks like this:

struct Entity {
    glm::vec3 Position;
    glm::vec3 Scale;
    glm::vec3 Rotation;
};

void turnEnemies() {
// the direction all ships look towards when spawned
    glm::vec3 defaultShipForward = glm::vec3( 0.0f, 0.0f, 1.0f );

    std::vector<Entity*> ships = ...;

    for (int i = 0; i < ships.size(); i++) {
        Entity* curShip = ships[i];
        if (curShip == m_player) continue;

// I only rotate the ships around the y-axis. 
// So I create a rotation matrix to rotate the ships default forward vector towards it's actual one
        glm::mat4 rotationMat = glm::rotate( glm::mat4( 1.0f ), curShip->Rotation.y, 
        glm::vec3( 0.0f, 1.0f, 0.0f ) );
        glm::vec3 curShipForward =  glm::normalize(rotationMat * glm::vec4(defaultShipForward, 1.0f));

// get the vector from the current ships position toward the player
        glm::vec3 vecToPlayer = glm::normalize( m_player->Position - ships[i]->Position );

        float turnAngle = getAngleBetweenVectorsDeg( curShipForward, vecToPlayer );

        ships[i]->Rotation.y += turnAngle;
    }
}

I implemented the following variants I found online for calculating the angle:

float getAngleBetweenVectorsDeg( glm::vec3 _vec1, glm::vec3 _vec2 ) {
    return acos( glm::dot( _vec1, _vec2 ) );
}
float getAngleBetweenVectorsDeg( glm::vec3 _vec1, glm::vec3 _vec2 ) {
    return  atan2( glm::length( glm::cross( _vec1, _vec2 ) ), glm::dot( _vec1, _vec2 ) );
}

With the acos solution, the rotation becomes undefined. The atan results in weird rotations, where one enemy rotates when the player moves forwards, the other when he moves backwards.

0 Answers
Related