# Blender Orient an object (displaying Vector Arrows)

I need to orient a various number of arrows on the screen, each need to point to a direction calculated by Python.

Python have calculated the end points of each arrow (say tail at (0,0,0), tip at (1,1,1)). How do I place an arrow between those two points, with the tail and tip at the correct spot with scripts?

My current plan is place the tail, then calculate the degree of rotation needed to get to the right direction, then rotate it. Is there potentially an easier/more direct way?

Optional: If the code does not scale the arrow, that's fine, as long as the arrow point in the right direction.

• – zeffii May 24 '15 at 17:28
• – p2or May 24 '15 at 20:33

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)]
]

# 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')


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

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)]
]

# 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')

# 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')


The .blend

(just hit run)

• I will give it a try. Yes, I am modelling the arrow once and duplicating. It's just placing it. – Darth Alpha May 24 '15 at 18:15
• Consider a [Track To] constraint which will rotate the arrow toward the location of a given target. The green arrow points to the red ball below, wherever the ball happens to be.

• In the animation below we see a few alternatives with constraints and modifiers

• The blue arrow is a curve in case you find the straight lines excessively boring. Circular cross section bevel. The curves has hook modifiers for the end points. A third point is added into the blender curve to introduce more [visual curve] into the blender curve. The visual curve is optional. The green cap is position with a [follow path] constraint. Of course this flexibility requires more work.
• The yellow arrow is an array modifier fit to curve straight line
• The large green arrow is the [track to] constraint as before
• The hook constraints

• That require another object right? Not just a point? It would mean I need to create an "point" object for every arrow I make---which can be somewhere from 10 to 50 depending on the situation. – Darth Alpha May 24 '15 at 17:57
• You can create en empty object which will not render. Any object can be set to NOT render. If you can place an arrow, then you can place an empty. Blender can handle a few x "thousand" empties. Assuming your computer executes blender at all. The red ball above was for illustrative purposes ... you may substitute an empty. Then it will be easy to use all the other facilities of blender with less python if that suits your tastes – atomicbezierslinger May 24 '15 at 18:00

Could not get the above solution to work, so here is another one:

import bpy
import mathutils

# calculates a vector (x, y, z) orthogonal to v
def getOrthogonal(v):

x = 0
y = 0
z = 0

if v[0] == 0: # x-axis is 0 => yz-plane

x = 1
y = 0
z = 0

else:

if v[1] == 0: # y-axis is 0 => xz-plane

x = 0
y = 1
z = 0

else:

if v[2] == 0: # z-axis is 0 => xy-plane

x = 0
y = 0
z = 1

else:

# x*v0 + y*v1 + z*v2 = 0
x = 1 / v[0]
y = 1 / v[1]
z = -((1/v[2]) * 2)

return (x, y, z)

def drawNormal(origin, normal):

b3 = mathutils.Vector(normal)

# find orthogonal basis vectors
b2 = mathutils.Vector(getOrthogonal(b3))
b1 = b2.cross(b3)

# normalize
b1.normalize()
b2.normalize()
b3.normalize()

# build transformation matrix
basis = mathutils.Matrix()
basis[0].xyz = b1
basis[1].xyz = b2
basis[2].xyz = b3
basis.transpose()
basis.translation = mathutils.Vector(origin)

# draw an arrow from normal
arrow = bpy.context.object
arrow.name = 'arrow'
arrow.empty_draw_type = 'SINGLE_ARROW'
arrow.matrix_basis = basis

# tests
# ----------------------------------------

# given origin and normal
origin = (0, 1, 0)
normal = (0, 1, 1)

drawNormal(origin, normal)

'''