17
$\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$
0

3 Answers 3

19
$\begingroup$

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

mathutils.Vector.to_track_quat in the docs

$\endgroup$
2
  • $\begingroup$ Thanks. I don't know how to include linebreaks in this mini-markdown format so, see my comment below... $\endgroup$
    – Batwam
    Dec 5, 2014 at 18:01
  • 1
    $\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, 2019 at 5:20
13
$\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$
1
  • $\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, 2017 at 12:38
5
$\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$
2
  • $\begingroup$ IMO need to bring further clarity to this answer. $\endgroup$
    – batFINGER
    Aug 6, 2018 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$ Aug 8, 2018 at 7:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .