0
$\begingroup$

Currently im trying to make an addon for the Space Colonization Algorithm in Blender. At the moment i only have a skeleton as a tree. Does anybody have an idea on how to thicken the tree so it does look somewhat realistic? I already tried the skin modifier, but that makes everywhere the same thickness and thinning it down by hand is not a possibility. And the bevel modifier behaves strangely since i probably have too many points. Thanks, Nebeig Tree example

edit: I tried it with the following code:

import bpy
radius = 0.4

obj = bpy.data.objects['Tree']

bpy.ops.object.modifier_add(type='SKIN')

for v in obj.data.skin_vertices[0].data:
radius -= 0.00025
v.radius = (radius,radius)

print(v.radius[:])

but blender chrashes when i try to execute the script.

    from random import randint, random, uniform
from copy import copy, deepcopy




def getDistance(p0, p1):
        return sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2 + (p0[2] - 
p1[2])**2)



   # importiert von https://blender.stackexchange.com/questions/5898/how-can-i- 
   create-a-cylinder-linking-two-points-with-python

class Tree:
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_label = 'Tools Tab Label'
    bl_context = 'objectmode'
    bl_category = 'SC'



def __init__(self):
    # Vektor operationen

    def div(x,y):
        return(x[0]/y, x[1]/y, x[2]/y)

    def sub(x,y):
        return(x[0]-y[0], x[1]-y[1], x[2]-y[2])

    def normieren(x,y):
        länge = sqrt(x[0]**2 + x[1]**2 + x[2]**2)
        return((x[0]/länge + x[1]/länge+ x[2]/länge)*y)

    def length_squared(u):
        return sum([a ** 2 for a in u])


    def add(u, v):    
        return [a + b for a, b in zip(u, v)]

    def norm(u):
        return setlength(u, 0.5)

    def scale_by_scalar(u, scalar):
        return [a * scalar for a in u]

    def length(u):
        return math.sqrt(length_squared(u))

    def setlength(u, l):
        return scale_by_scalar(u, l / length(u))

    branches = []
    leaves = [] 
    verts = ()
    closeEnough = 0 # False

    #leaves generieren
    for i in range(0,150):
        leaves.append(Leaf((uniform(-4.0,4.0),uniform(-4.0,4.0),uniform(4.0,9.0)),0))
        #bpy.ops.mesh.primitive_uv_sphere_add(size=0.1, location=leaves[i].pos)
        i =+ 1

    #Stamm machen    
    root = Branch(None,(0,0,0),(0,0,0.5))
    branches.append(root)
    current = root       

    max_dist = 3
    min_dist = 1
    while closeEnough == 0: # False             
        for i in range (len(leaves)):
            g = 0
            g = getDistance(current.pos, leaves[i].pos)
            #print(g)
            if (g < max_dist):
                print('schlaufe 1')
                closeEnough = 1
            if (closeEnough == 0):
                print('         schlaufe 2          ')
                nextPos = tuple(add(branches[i].pos,branches[i].dir))
                branch = Branch(i,nextPos,branches[i].dir)
                current = branch
                branches.append(current)
                if (g > 100):
                    break


    #Der eigentliche Algorithmus                    
    def grow(self):           
        self.record = 100000
        for i in range(len(leaves)):
            leaf = leaves[i]
            closestBranch = None
            self.closestDir = None

            #Den nächsten Ast bestimmen
            for j in range(len(branches)):
                #print(j) 
                branch = branches[j]
                dir = sub(leaf.pos ,branch.pos)
                d = length(dir)
                #print(d)
                if (d < min_dist):
                    leaf.reached()
                    break
                #elif(d > max_dist):      
                elif (closestBranch == None or d < self.record):
                    closestBranch = branch
                    self.record = d

            #Dessen Richtung bestimmen                              
            if (closestBranch is not None):
                newDir = tuple(sub(leaf.pos, closestBranch.pos))
                newDirnormed = norm(newDir)
                #print(newDir)
                closestBranch.dir = tuple(add(closestBranch.dir, 
   newDirnormed))
                closestBranch.count += 1

        #alle Blätter entfernen die erreicht wurden                       
        for i in reversed(range(len(leaves))):
            if (leaves[i].erreicht == 1):
                del(leaves[i])

        branchcopy = deepcopy(branches)    
        #print(branches[0].dir)                                       
        for i in reversed(range(len(branches))):
            branch = branches[i]
            #print(branch.count)            
            if (branch.count > 0):               
                branch.dir = tuple(div(branch.dir,branch.count))
                newPos = tuple(add(branch.pos,branch.dir))
                newB = Branch(i, newPos, branch.dir)
                branches.append(newB)
                branch.reset()


    for i in range(70):    
        grow(self)

    # this assumes all vertex positions are unique (= do not overlap)
    # create a mapping from vertex position to vertex index 
    verts = {b.pos:i for i,b in enumerate(branches)}
    # create vertex pairs as edge by locating vert index based on 
coordinates
    edges = [ (verts[b.pos],verts[branches[b.parent].pos])for b in branches
    if b.parent is not None]
    # replace vertex mapping by simple list of coordinates
    verts = [b.pos for b in branches]

    mesh = bpy.data.meshes.new("tree_mesh")
    mesh.from_pydata(verts, edges, faces=[])
    mesh.update()

    obj = bpy.data.objects.new("Tree", mesh)

    scene = bpy.context.scene
    scene.objects.link(obj)
    #remove doubles muss man noch machen


    obj = bpy.data.objects['Tree']
    for v in obj.vertices:
        v.select = True
        bpy.ops.transform.skin_resize(value=(0.695461, 0.695461, 0.695461))
        v.deselect = True


tree= Tree()
$\endgroup$
2
  • 1
    $\begingroup$ If you add the skin modifier to your mesh, it will create a 'skin_vertices' object in it, where you can access to the radius of the vertices... For example: bpy.data.objects['Obj'].data.skin_vertices[''].data[0].radius = (1.0, 1.0) $\endgroup$
    – Secrop
    Jul 20, 2018 at 10:56
  • $\begingroup$ Probably something wrong with your mesh... that script works ok here. Post your blend file for inspection. $\endgroup$
    – Secrop
    Jul 20, 2018 at 14:17

2 Answers 2

1
$\begingroup$

I resolved the problem by setting the name of the radius variable to something different than radius.

$\endgroup$
0
$\begingroup$

Try the Sapling Tree Gen add-on. You should have it in your copy of Blender and activate it.

$\endgroup$
0

You must log in to answer this question.

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