Calculate angle between two vectors in 3d

Viewed 103

I have to connect two atoms (spheres). I can calculate position and length of required connection but struggle to calculate rotation angle. I use rotation matrices to complete the rotation. So I need to specify XYZ angles to build this matrices and perform the actual rotation.

So what I do:

  1. Get vector between atoms represented by points a and b.
float3(b[0] - a[0], b[1] - a[1], b[2] - a[2])
  1. Cylinders are vertical by default so their vector is float3(0, 10, 0)
  2. For each pair of coordinates I am trying to calculate rotation angle so:
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)
}

What am I doing wrong? Thank you in advance!

enter image description here

2 Answers

To find angles between two vectors in 3D space you could use this function:

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

This solved it! Source

Related