3 votes

Calculer l'angle entre deux vecteurs en 3D

Je dois connecter deux atomes (sphères). Je peux calculer la position et la longueur de la connexion requise mais j'ai du mal à calculer l'angle de rotation. J'utilise des matrices de rotation pour compléter la rotation. Je dois donc spécifier les angles XYZ pour construire ces matrices et effectuer la rotation réelle.

Donc ce que je fais :

  1. Obtenir le vecteur entre les atomes représenté par les points a et b.

    float3(b[0] - a[0], b[1] - a[1], b[2] - a[2])

  2. Les cylindres sont verticaux par défaut donc leur vecteur est float3(0, 10, 0)

  3. Pour chaque paire de coordonnées, j'essaie de calculer l'angle de rotation donc :

    cylinder v = float3(0, 10, 0) atomV = float3(...)

    X = getAngle(v[1], v[2], atomV[1], atomV[2]) Y = getAngle(v[0], v[2], atomV[0], atomV[2]) Z = getAngle(v[0], v[1], atomV[0], atomV[1])

    getAngle(x1: Float, y1: Float, x2: Float, y2: Float)->Float { return atan2(x1 y2 - y1 x2, x1 x2 + y1 y2) }

Qu'est-ce que je fais mal? Merci d'avance!

Description de l'image ici

1voto

0xBFE1A8 Points 1414

Pour trouver les angles entre deux vecteurs dans l'espace 3D, vous pourriez utiliser cette fonction :

    float clampValue(float value, float min, float max) {
        if(value < min)
            value = min;
        else if (value > max)
            value = max;
        return value;
    }

    float degreesFromRadians(float radians) {
        return (radians / M_PI) * 180;
    }

    float angle(float3 v1, float3 v2) {
        float kEpsilonNormalSqrt = 1e-15F;

        float sqrMagnitudeV1 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
        float sqrMagnitudeV2 = v2.x * v2.x + v2.y * v2.y + v2.z * v2.z;

        float denominator = sqrtf(sqrMagnitudeV1 * sqrMagnitudeV2);

        float dotProduct = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;

        if(denominator < kEpsilonNormalSqrt)
            return 0;

        float v = clampValue(dotProduct / denominator, -1, 1);

        return degreesFromRadians(acosf(v));
    }

0voto

mat3 rotateAlign( vec3 v1, vec3 v2)
{
    vec3 axis = cross( v1, v2 );

    const float cosA = dot( v1, v2 );
    const float k = 1.0f / (1.0f + cosA);

    mat3 result( (axis.x * axis.x * k) + cosA,
                 (axis.y * axis.x * k) - axis.z, 
                 (axis.z * axis.x * k) + axis.y,
                 (axis.x * axis.y * k) + axis.z,  
                 (axis.y * axis.y * k) + cosA,      
                 (axis.z * axis.y * k) - axis.x,
                 (axis.x * axis.z * k) - axis.y,  
                 (axis.y * axis.z * k) + axis.x,  
                 (axis.z * axis.z * k) + cosA 
                 );

    return result;
}

Cela a résolu le problème! Source

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X