Search code examples
3dmetal

Calculate angle between two vectors in 3d


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


Solution

  • 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