14
$\begingroup$

I am trying to rotate an object using python, inline with a vector which gives me the direction I want (based on the difference between the last two coordinates of the curve I generated). I therefore have a vector which I'd like to align this object but not the XYZ angles. The options to specify rotation (XYZ Euler...) all seem to require some sort of angle definition. I've started playing with numpy with I'm not experienced enough to find the answer.

Would you be able to advise what would be the best way to align an object to a vector and (if necessary) how I could convert the vector coordinates in XYZ_Euler angles I could apply to the object?

for instance, Vector=[1,1,1] and I would like to rotate the object along this vector.

Thanks for your help


update

Thanks guys, DirectionVector.to_track_quat('X', 'Z') did the trick very nicely!

#define direction
Vector=(1,1,1)
DirectionVector = mathutils.Vector(Vector) 
#apply rotation
bpy.context.object.rotation_mode = 'QUATERNION'
bpy.context.object.rotation_quaternion = DirectionVector.to_track_quat('Z','Y')
$\endgroup$
15
$\begingroup$

Try this: DirectionVector.to_track_quat('X', 'Z').to_euler()

mathutils.Vector.to_track_quat in the docs

$\endgroup$
  • $\begingroup$ Thanks. I don't know how to include linebreaks in this mini-markdown format so, see my comment below... $\endgroup$ – hyg53 Dec 5 '14 at 18:01
  • $\begingroup$ For me, for pointing a camera, what I needed was camera.rotation_euler = direction_vec.to_track_quat('-Z', 'Y').to_euler() $\endgroup$ – colllin Mar 31 '19 at 5:20
9
$\begingroup$

This example uses Vector.rotation_difference or Vector.to_track_quat

import bpy
from mathutils import Matrix, Vector, Euler

obj = bpy.context.active_object
vec = Vector((1.0, 1.0, 1.0))

# object axis to align with vector vec
axis = Vector((1.0, 0.0, 0.0))

# rotation difference
q = axis.rotation_difference(vec)
# or
# track quaternion
q = vec.to_track_quat('X', 'Z')

loc, rot, scale = obj.matrix_world.decompose()

mat_scale = Matrix()
for i in range(3):
    mat_scale[i][i] = scale[i]

obj.matrix_world = (
    Matrix.Translation(loc) * 
    q.to_matrix().to_4x4() * 
    mat_scale)
$\endgroup$
  • $\begingroup$ Hi Jerryno, could you please have a look at my question found here blender.stackexchange.com/questions/79344/… batFINGER suggested that this answer could help me solve what I'm trying to do. I'd appreciate it if you could advise me please. $\endgroup$ – Tak May 10 '17 at 12:38
1
$\begingroup$

Yes thanks for that final hint. Super simple in my case.

[At first I had my up and nrml switched.]

up = Vector((0, 0, 1))
rot = up.rotation_difference(nrml).to_euler()
print("normal:", nrml, "rotation:", rot)
bpy.ops.mesh.primitive_circle_add(vertices=36, radius=siz, fill_type='NGON', location=cntr, rotation=rot)

May it bring further clarity to others.

$\endgroup$
  • $\begingroup$ IMO need to bring further clarity to this answer. $\endgroup$ – batFINGER Aug 6 '18 at 16:31
  • $\begingroup$ Hmmm it's just a simplification in another context. How to get the Euler Rotation for items that need that. nrml is of course a Normal or angle you are aligning to typically in this case it came from a polygon (aka face) via p.normal as does the cntr from p.center. I was experiencing odd behavior and then tried switching the nrml and up in the line with rotation_difference and then it all started working so again just a hint to other that if your experiencing weird behavior try that. If you need more clarity maybe be more specific but it's again not worth our time, but could be useful. $\endgroup$ – Master James Aug 8 '18 at 7:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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