Recalculate Bone Roll Angles from python

Hi, Can any one tell me how to achieve equivalent of Ctrl+N in edit mode of the armature (to recompute bone roll angles).

ok. I found some leads in to this. Here is the C code inside blender that does this:

                /* Z-Axis Point Up */
                float    xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0, 0.0, 1.0};
                float    targetmat[3][3], imat[3][3], diffmat[3][3];
                
                /* Find the current bone matrix */
                VecSubf(delta, ebone->tail, ebone->head);
                vec_roll_to_mat3(delta, 0.0, curmat);
                
                /* Make new matrix based on y axis & z-up */
                VECCOPY (yaxis, curmat[1]);
                
                Mat3One(targetmat);
                VECCOPY (targetmat[0], xaxis);
                VECCOPY (targetmat[1], yaxis);
                VECCOPY (targetmat[2], zaxis);
                Mat3Ortho(targetmat);
                
                /* Find the difference between the two matrices */
                Mat3Inv(imat, targetmat);
                Mat3MulMat3(diffmat, imat, curmat);
                
                ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);

It is there in source/blender/src/editarmature.c file and in auto_align_armature function. I will try to figure out the python equivalent of this. If any one else is also interested I can post the python code once I am done.

I managed to write equivalent python code. But it does not seem to work :frowning: I guess at this point it will require some pros to have a look at it --------------------------------------------------------------------------------------- import Blender from Blender import * from Blender.Mathutils import * import math from math import * def MatMult(rMatrix, bMatrix): mat = Matrix([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]) mat[0][0] = rMatrix[0][0]*bMatrix[0][0]+rMatrix[0][1]*bMatrix[1][0]+rMatrix[0][2]*bMatrix[2][0] mat[0][1] = rMatrix[0][0]*bMatrix[0][1]+rMatrix[0][1]*bMatrix[1][1]+rMatrix[0][2]*bMatrix[2][1] mat[0][2] = rMatrix[0][0]*bMatrix[0][2]+rMatrix[0][1]*bMatrix[1][2]+rMatrix[0][2]*bMatrix[2][2] mat[1][0] = rMatrix[1][0]*bMatrix[0][0]+rMatrix[1][1]*bMatrix[1][0]+rMatrix[1][2]*bMatrix[2][0] mat[1][1] = rMatrix[1][0]*bMatrix[0][1]+rMatrix[1][1]*bMatrix[1][1]+rMatrix[1][2]*bMatrix[2][1] mat[1][2] = rMatrix[1][0]*bMatrix[0][2]+rMatrix[1][1]*bMatrix[1][2]+rMatrix[1][2]*bMatrix[2][2] mat[2][0] = rMatrix[2][0]*bMatrix[0][0]+rMatrix[2][1]*bMatrix[1][0]+rMatrix[2][2]*bMatrix[2][0] mat[2][1] = rMatrix[2][0]*bMatrix[0][1]+rMatrix[2][1]bMatrix[1][1]+rMatrix[2][2]bMatrix[2][1] mat[2][2] = rMatrix[2][0]bMatrix[0][2]+rMatrix[2][1]bMatrix[1][2]+rMatrix[2][2]bMatrix[2][2] return mat def VecLenf(v1, v2): x = v1[0]-v2[0] y = v1[1]-v2[1] z = v1[2]-v2[2] return sqrt(xx+yy+zz) def saasin(fac): M_PI = 3.14159265358979323846 if (fac = 1.0): return M_PI/2.0 else: return asin(fac) def NormalizedVecAngle2(v1, v2): M_PI = 3.14159265358979323846 dotp12 = DotVecs(v1, v2) vec = Vector([0.0,0.0,0.0]) if (dotp12 < 0.0): vec[0] = -v2[0] vec[1] = -v2[1] vec[2] = -v2[2] return (M_PI - 2.0saasin(VecLenf(vec, v1)/2.0)) else: return 2.0saasin(VecLenf(v2, v1)/2.0) def vec_roll_to_mat3(vec, roll): bMatrix = Matrix([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]) rMatrix = Matrix([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]) nor = vec.copy() nor.normalize() target = Vector([0.0,1.0,0.0]) axis = CrossVecs(target, nor) axislen2 = DotVecs(axis, axis) if (axislen2 > 0.0000000000001): axis.normalize() theta = NormalizedVecAngle2(target, nor) bMatrix = RotationMatrix(theta, 3, ‘r’, axis) else: updown = 0.0 dotptmp = DotVecs(target, nor) if (dotptmp > 0.0): updown = 1.0 else: updown = -1.0 bMatrix[0][0] = updown bMatrix[1][1] = updown bMatrix[2][2] = updown rMatrix = RotationMatrix(roll, 3, ‘r’, nor) mat = MatMult(rMatrix, bMatrix) #print vec, nor #print mat return mat def RoleAnglesWithZUp(ebone): xaxis = Vector([1.0,0.0,0.0]) yaxis = Vector([0.0,0.0,0.0]) zaxis = Vector([0.0,0.0,1.0]) delta = ebone.tail - ebone.head curmat = vec_roll_to_mat3(delta, 0.0) yaxis = curmat[1].copy() targetmat = Matrix([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]) targetmat.identity() targetmat[0] = xaxis.copy() targetmat[1] = yaxis.copy() targetmat[2] = zaxis.copy() targetmat[0].normalize() targetmat[1].normalize() targetmat[2].normalize() #print targetmat targetmat.invert() #print targetmat diffmat = MatMult(targetmat, curmat) ebone.roll = atan2(diffmat[2][0], diffmat[2][2]) print ebone.roll

oops! I dont know how to paste the code correctly. Any help?