1

I am new to Blender and I want to create an array of 3D arrows; the array itself is 2*2 (constant space between each object) but the arrows are 3D.

I hope to write a python code for it but I don't know where to start. There is a code in the following link for a single 3D arrow, but I'm afraid I cannot use it.

Blender Orient an object (displaying Vector Arrows)

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187
Rex
  • 11
  • 1
  • 1
  • 1
    This isn’t very clear. Can you draw what you were trying to do? I mean, if all you want is an array of arrows, you can just use the array modifier and get 400 arrows all pointing in the same direction. Also, I know you’re trying to help, but saying “I am new to Blender“ doesn’t really specify anything. Some ideas of being “new to blender“ means that they haven’t used it for more than a year. – TheLabCat May 14 '22 at 22:05
  • Thanks for the reply. Sorry for not being clear. I started working with Blender 2-3 months ago (not full-time though, occasionally I can say). 99% of the time, I draw objects without using python; just recently I started to use python. I can definitely draw what I am hoping to do, but for some reasons I want to use scripting because it adds flexibility for future use as well as if I want to extend my draw, it would be pretty easy. Regarding this structure, although I said array, actually I am going to draw a hexagonal/honeycomb lattice. But to start, array is an easier place to start. Thanks – Rex May 14 '22 at 22:19
  • I would try geometry nodes before scripting in this case. – TheLabCat May 14 '22 at 22:43
  • So… is the question[s]: “how to create an arrow mesh (if so what are the specs of the arrow); how to duplicate linked an object in desired positions, and (not about blender) how to generate a honeycomb lattice of points, in Python” – TheLabCat May 15 '22 at 04:19
  • 1
    Hi, sorry for the delay. yes, the question is how to create an arrow (mesh) with python. Thanks – Rex May 16 '22 at 14:53

1 Answers1

2

Here's something I wrote that I think you might find useful. v0, v1, and v2 are three corners of a square and I used nested for loops to create an array of arrows. To create the arrows themselves, I wrote a mesh-from-scratch function "createArrow". Let me know if I need to fix anything.

import bpy
from math import *
from mathutils import Vector

def createArrow(tubeRadius, arrowLength, headLength, tubeLength, tubeAcross, tubeAround, headAround, headRadius, arrows):

verts = []
edges = []
faces = []
#append tube verticies 0 thru (tubeAcross x tubeAround - 1)
for i in range(tubeAcross):
    v1 = tubeLength * (i / (tubeAcross - 1)) #- length/2
    for j in range(tubeAround):
        angle = 2 * pi * j / tubeAround
        v2 = tubeRadius * cos(angle)
        v3 = tubeRadius * sin(angle)

        verts.append([v1, v2, v3])

        index1 = tubeAround * i + j
        index2 = tubeAround * i + j + 1
        if index2 == (i + 1) * tubeAround:
            index2 = i * tubeAround
        edge = [index1, index2]
        edges.append(edge)

#append cone verts (tubeAcross x tubeAround) thru (tubeAcross x tubeAround + coneAround + 1) (exctra 1 for the tip)
for i in range(headAround):
    angle = 2 * pi * i / headAround
    v1 = tubeLength
    v2 = headRadius * cos(angle)
    v3 = headRadius * sin(angle)
    verts.append([v1, v2, v3])

verts.append([arrowLength, 0, 0])

#append tube faces:
# for i in range of number of faces (added 1 for the circle face)
for i in range(tubeAround * (tubeAcross - 1) + 1):
    face = []
    if i == 0:
        # make face out of first slicesAround edges:
        for j in range(tubeAround):
            face.append(edges[j][0])
    else:
        face = [edges[i - 1][0], edges[i - 1][1], edges[i - 1 + tubeAround][1], edges[i - 1 + tubeAround][0]]

    faces.append(face)

#append face for back of cone:
face = []
for i in range(headAround):
    face.append(tubeAround*tubeAcross + i)
faces.append(face)

#append cone faces:
for i in range(headAround):
    index1 = tubeAcross * tubeAround  + i
    index2 = tubeAcross * tubeAround + i + 1
    index3 = tubeAcross * tubeAround + headAround

    if index2 == index3:
        index2 = index2 - headAround


    face = [index1, index2, index3]
    faces.append(face)



mesh = bpy.data.meshes.new("Arrow")
arrow = bpy.data.objects.new("Arrow", mesh)
#col = bpy.data.collections.get("Collection")
#col.objects.link(bendableArrow)
arrows.objects.link(arrow)
mesh.from_pydata(verts, [], faces)




---------------MAIN--------------------

#creation variables headRadius = .1 tubeAcross = 2 tubeAround = 50 headAround = 50 tubeRadius = headRadius/2

arrows = bpy.data.collections.new("Arrows") bpy.context.scene.collection.children.link(arrows)

numAcross = 5 v0 = Vector([-1, 1, 0]) v1 = Vector([-1, -1, 0]) v2 = Vector([1, 1, 0])

for i in range(numAcross): for j in range(numAcross):

    tip = v0 + (i/(numAcross - 1)) * (v2 - v0) + (j/(numAcross - 1)) * (v1 - v0)      

    arrowLength = tip.magnitude

    headLength = sqrt(3 * headRadius**2)

    tubeLength = arrowLength - headLength

    createArrow(tubeRadius, arrowLength, headLength, tubeLength, tubeAcross, tubeAround, headAround, headRadius, arrows)

    arrow = arrows.objects[j + i*numAcross]

    for f in arrow.data.polygons:
        f.use_smooth = True

    arrow.data.use_auto_smooth = 1
    arrow.data.auto_smooth_angle = radians(30)

    x = tip.x
    y = tip.y
    z = tip.z
    mag = sqrt(x**2 + y**2)


    if x == 0 and y >= 0:
        theta = pi/2
    elif x == 0 and y < 0:
        theta = -pi/2

    elif x < 0:
        theta = pi + atan(y/x)
    else:
        theta = atan(y/x)


    if mag == 0 and z >= 0:
        beta = pi/2
    elif mag == 0 and z < 0:
        beta = -pi/2
    elif mag < 0:
        beta = pi + atan(z/mag)
    else:
        beta = atan(z/mag)


    arrow.rotation_euler = (0, beta, theta)

Adam Swearingen
  • 1,160
  • 4
  • 12
  • Hi Adam717, sorry for the delayed reply. Thanks for the code. I checked it quickly, and it is great. I can start working on it. Thanks. I'll let you know if I have any questions. – Rex May 26 '22 at 19:39