Full credit should go to: align-object-to-vector-using-python for the API usage of Quaternion
and to_track_quat
.
downside to the following methods:
They aren't dynamic, unlike the proposed method that uses constraints.
Single Size Arrows
Model the arrow once, make duplicates :)
import bpy
import bmesh
import mathutils
from mathutils import Vector
scene = bpy.context.scene
arrow_mesh = bpy.data.objects['ArrowObject'].data
vectors = [
[(0,0,1), (0,0,0)],
[(0,1,0), (0,0,0)],
[(1,0,0), (0,0,0)],
[(1,1,1), (0,0,0)]
]
for head, tail in vectors:
v1, v2 = Vector(head), Vector(tail)
# duplicate mesh into new object.
obj = bpy.data.objects.new("Arrow_duplicate", arrow_mesh)
obj.location = v2
obj.rotation_mode = 'QUATERNION'
obj.rotation_quaternion = (v1-v2).to_track_quat('Z','Y')
scene.objects.link(obj)
Be sure to have the Arrow's object origin on the tail, and coinciding with the axis of the Arrow. (just in-case)
It may be worth mentioning that this code won't stretch the arrow to exactly fit between head and tail vectors, but it will place the arrows tail/origin at exactly the tail vector and point to the correct head-vector. As soon as you need the arrow to fit exactly between the two vectors you introduce a different problem, with several solutions
Adaptive arrow scaling
description:
- A cone which you can orient given similar code
- A stem which takes orientation and scaling in its length-wise axis.
code:
import bpy
import bmesh
import mathutils
from mathutils import Vector
scene = bpy.context.scene
objects = bpy.data.objects
arrow_stem_mesh = objects['Arrow_stem'].data
arrow_cone_mesh = objects['Arrow_cone'].data
arrow_cone_height = 0.448 # for example..
vectors = [
[(0,0,1), (0,0,0)],
[(0,1,0), (0,0,0)],
[(1,0,0), (0,0,0)],
[(1,1,1), (0,0,0)],
[(2,2,2), (3,3,3)],
[(4,4,2), (2,2,2)],
[(4,4,3), (2,0,0)]
]
for head, tail in vectors:
v1, v2 = Vector(head), Vector(tail)
# Scale the Stem, and add to scene
obj = bpy.data.objects.new("Arrow_duplicate", arrow_stem_mesh)
obj.location = v2
obj.scale = (1, 1, (v1-v2).length)
obj.rotation_mode = 'QUATERNION'
obj.rotation_quaternion = (v1-v2).to_track_quat('Z','Y')
scene.objects.link(obj)
# orient Cone, and add to scene
obj2 = bpy.data.objects.new("Arrow_duplicate", arrow_cone_mesh)
obj2.location = v1 # start at tail and work back
obj2.rotation_mode = 'QUATERNION'
obj2.rotation_quaternion = (v1-v2).to_track_quat('Z','Y')
scene.objects.link(obj2)
The .blend
(just hit run)