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

1 Answer 1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.