1
$\begingroup$

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)

$\endgroup$
5
  • 1
    $\begingroup$ 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. $\endgroup$
    – TheLabCat
    Commented May 14, 2022 at 22:05
  • $\begingroup$ 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 $\endgroup$
    – Rex
    Commented May 14, 2022 at 22:19
  • $\begingroup$ I would try geometry nodes before scripting in this case. $\endgroup$
    – TheLabCat
    Commented May 14, 2022 at 22:43
  • $\begingroup$ 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” $\endgroup$
    – TheLabCat
    Commented May 15, 2022 at 4:19
  • 1
    $\begingroup$ Hi, sorry for the delay. yes, the question is how to create an arrow (mesh) with python. Thanks $\endgroup$
    – Rex
    Commented May 16, 2022 at 14:53

1 Answer 1

2
$\begingroup$

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)
$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$
    – Rex
    Commented May 26, 2022 at 19:39

You must log in to answer this question.

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