Take the 2-minute tour ×
Blender Stack Exchange is a question and answer site for people who use Blender to create 3D graphics, animations, or games. It's 100% free, no registration required.

How to do this?

Below is my particular use case and attempt to solve the problem:


Consider Z_axis = (0,0,1) and an arbitrary point also on the unit sphere v.

You can imagine the arc on the surface of the sphere from Z_axis to v.

I wish to create v' by extending the arc by 10%.

How can I do this from Python?

Here is as far as I have got:

unit_v = v.normalized()
rot_axis = Z_axis.cross(unit_v)

...will give a vector perpendicular to rotation plane, and

theta = arcsin( abs(rot_axis) ) # <-- some potential problem with positive and negative angles here I think

...will return the angle.

So I was just need to rotate unit_v by theta' = 0.1*theta around rot_axis

How do I do this?

I can construct a Quaternion Q representing the rotation:

w = cos( theta'/2 )
x,y,z = sin( theta'/2 ) * rot_axis.normalized()

Q = Quaternion(( w,x,y,z ))

and then:

unit_v' = unit_v.rotate(Q)
v' = abs(v) * unit_v'

Is this correct, and is there a cleaner way?

(ref: http://www.essentialmath.com/GDC2013/GDC13_quaternions_final.pdf)

share|improve this question

2 Answers 2

up vote 8 down vote accepted

Blender 2.71 (or any recent build) has Vector.slerp (spherical linear interpolation) which accepts values outside 0-1

So you can do:

a = Vector((1, 0, 0))
b = Vector((0, 1, 0))
c = a.slerp(b, 0.5)  # half way

To over rotate 10% do:

c = a.slerp(b, 1.1)

Note, this feature is not included in a stable release yet (but 2.71 will include it).

share|improve this answer

As @ideasman42 said you can use slerp for the rotation in coming releases, but until then, I think Quaternions are a good solution.
However if you want to rotate a large number of points, rotation matrices is faster. Rotating a point p using a quaternion q works as follows:

(0,p') = q * (0,p) * q^

where (0,p) is a quaternion with a w value of 0 and the x, y and z value of p and q^ is the conjugated quaternion of q. * denotes the quaternion multiplication.
This is what quaternion multiplication looks like if broken into bits:

q1*q2 = (w1,x1,y1,z1)*(w2,x2,y2,z2)
      = ( w1*w2-x1*x2-y1*y2-z1*z2 ,
          w1*x2+x1*w2+y1*z2-z1*y2 ,
          w1*y2+y1*w2+z1*x2-x1*z2 ,
          w1*z2+z1*w2+x1*y2-y1*x2  )

Both quaternion multiplications internally need 16 floatingpoint multiplications and 12 floatingpoint additions (seeing subtractions as additions with negative numbers).

Total cost:
32 multiplications
24 additions

Rotating a point using a rotation matrix as follows:

p' = R * p

where R is the rotation matrix and * denotes the matrix multiplication. Note that p is a column vector.
Even if Blender imbeds the rotation matrix in a 4x4 transformation matrix and uses 4D homogenuous points in the calculation this results in less computation steps:

      |r11 r12 r13 r14|   |px|   |r11*px+r12*py+r13*pz+r14*pw|
R*p = |r21 r22 r23 r24| * |py| = |r21*px+r22*py+r23*pz+r24*pw|
      |r31 r32 r33 r34|   |pz|   |r31*px+r32*py+r33*pz+r34*pw|
      |r41 r42 r43 r44|   |pw|   |r41*px+r42*py+r43*pz+r44*pw|

Total cost:
16 multiplications
12 additions

If Blender internally only uses 3x3 matrices and normal 3D points the calculations get even more performant (9 multiplications and 6 additions).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.