Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2007-11-27 14:57:18 +0300
committerCampbell Barton <ideasman42@gmail.com>2007-11-27 14:57:18 +0300
commit2a743951fcd8af803a3d9bcfec0ffae7769e0750 (patch)
tree62824c18b6b37ff01a9c02edd84120ef366bb818 /release
parent01e2395e057b6fd4c601312bb2feb8bd2888692b (diff)
* Improved Fill Twigs, they now join to make a continues skin like other branches.
* Improved dupli-leaf placement - (should be good enough to use for final renders)
Diffstat (limited to 'release')
-rw-r--r--release/scripts/wizard_curve2tree.py703
1 files changed, 384 insertions, 319 deletions
diff --git a/release/scripts/wizard_curve2tree.py b/release/scripts/wizard_curve2tree.py
index 497597262a8..620a0bcdf67 100644
--- a/release/scripts/wizard_curve2tree.py
+++ b/release/scripts/wizard_curve2tree.py
@@ -41,10 +41,17 @@ import Blender
import BPyMesh
from Blender.Mathutils import Vector, Matrix, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
from Blender.Geometry import ClosestPointOnLine
+from Blender.Noise import randuvec
GLOBALS = {}
GLOBALS['non_bez_error'] = 0
+def AngleBetweenVecsSafe(a1, a2):
+ try:
+ return AngleBetweenVecs(a1,a2)
+ except:
+ return 180.0
+
# Copied from blender, we could wrap this! - BKE_curve.c
# But probably not toooo bad in python
def forward_diff_bezier(q0, q1, q2, q3, pointlist, steps, axis):
@@ -146,6 +153,10 @@ def next_random_num(rnd):
eul = 0.00001
+BRANCH_TYPE_CURVE = 0
+BRANCH_TYPE_GROWN = 1
+BRANCH_TYPE_FILL = 2
+
class tree:
def __init__(self):
self.branches_all = []
@@ -214,6 +225,8 @@ class tree:
brch = branch()
+ brch.type = BRANCH_TYPE_CURVE
+
self.branches_all.append(brch)
bez_list = list(spline)
@@ -221,13 +234,15 @@ class tree:
bez1 = bez_list[i-1]
bez2 = bez_list[i]
points_from_bezier_seg(self.steps, pointlist, radlist, bez1.vec, bez2.vec, bez1.radius, bez2.radius)
- bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii] * self.limbScale) for ii in xrange(len(pointlist)) ]
+
+
# remove endpoint for all but the last
+ len_pointlist = len(pointlist)
if i != len(bez_list)-1:
- bpoints.pop()
+ len_pointlist -= 1
- brch.bpoints.extend(bpoints)
+ brch.bpoints.extend([ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii] * self.limbScale) for ii in xrange(len_pointlist) ])
# Finalize once point data is there
brch.calcData()
@@ -653,6 +668,8 @@ class tree:
'''
+ rnd = [1]
+
segments_all = []
segments_level = []
@@ -706,9 +723,10 @@ class tree:
if twig_fill_shape_rand==0.0:
return (parentCo + ch1Co + ch2Co) / 3.0
else:
- w1 = Rand(0.0, twig_fill_shape_rand) + (1-twig_fill_shape_rand)
- w2 = Rand(0.0, twig_fill_shape_rand) + (1-twig_fill_shape_rand)
- w3 = Rand(0.0, twig_fill_shape_rand) + (1-twig_fill_shape_rand)
+
+ w1 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
+ w2 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
+ w3 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand)
wtot = w1+w2+w3
w1=w1/wtot
w2=w2/wtot
@@ -739,9 +757,30 @@ class tree:
self.brothers = []
self.no = Vector() # only endpoints have these
- self.id = len(segments_all)
- self.bpt = None # branch point for root segs only
+ # self.id = len(segments_all)
+
+ # First value is the bpoint,
+ # Second value is what to do -
+ # 0 - dont join
+ # 1 - Join to parent (tree point)
+ # 2 - join to parent, point from another fill-twig branch we just created.
+ self.bpt = (None, False) # branch point for root segs only
+ self.new_bpt = None
+
+ self.used = False # use this to tell if we are apart of a branch
+
+ def sibling(self):
+ i = self.parent.children.index(self)
+
+ if i == 0:
+ return self.parent.children[ 1 ]
+ elif i == 1:
+ return self.parent.children[ 0 ]
+ else:
+ raise "error"
+
+
def getHeadHandle(self):
"""
For Bezier only
@@ -803,7 +842,9 @@ class tree:
for seg_child in self.children:
seg_child.calcLevelFromRoot()
-
+
+ # Dont use for now, but scale worked, transform was never tested.
+ """
def transform(self, matrix):
self.headCo = self.headCo * matrix
self.tailCo = self.tailCo * matrix
@@ -829,13 +870,14 @@ class tree:
if self.children:
self.children[0].scale(scale, cent)
self.children[1].scale(scale, cent)
-
+ """
def recalcChildLoc(self):
if not self.children:
return
ch1 = self.children[0]
ch2 = self.children[1]
new_mid = mergeCo(self.headCo, ch1.tailCo, ch2.tailCo, twig_fill_shape_rand)
+
self.tailCo[:] = ch1.headCo[:] = ch2.headCo[:] = new_mid
ch1.recalcChildLoc()
@@ -845,14 +887,41 @@ class tree:
"""
Merge other into self and make a new segment
"""
+ """
+ seg_child = segment(self.levelFromLeaf)
+ self.levelFromLeaf += 1
+
+ seg_child.parent = other.parent = self
+
+ # No need, recalcChildLoc sets the other coords
+ #self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0
+ #self.parent.headCo[:] = self.headCo
+
+ seg_child.headCo[:] = self.headCo
+
+ # isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo)
+ # new_head = (isect[0]+isect[1]) * 0.5
+
+ seg_child.mergeCount += 1
+ other.mergeCount += 1
+
+ self.children.extend([ seg_child, other ])
+
+ self.recalcChildLoc()
+
+ # print 'merging', self.id, other.id
+ """
#new_head = (self.headCo + self.tailCo + other.headCo + other.tailCo) * 0.25
+
self.parent = other.parent = segment(self.levelFromLeaf + 1)
- self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0
+ # No need, recalcChildLoc sets the self.parent.tailCo
+ # self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0
+
self.parent.headCo[:] = self.headCo
self.parent.bpt = self.bpt
- self.bpt = None
+ self.bpt = (None, False)
# isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo)
# new_head = (isect[0]+isect[1]) * 0.5
@@ -865,6 +934,7 @@ class tree:
self.parent.recalcChildLoc()
# print 'merging', self.id, other.id
+
def findBestMerge(self, twig_fill_fork_angle_max):
# print "findBestMerge"
if self.parent != None:
@@ -903,7 +973,7 @@ class tree:
def getLength(self):
return (self.headCo - self.tailCo).length
-
+ """
def toMatrix(self, LEAF_SCALE, LEAF_RANDSCALE, LEAF_RANDVEC):
if LEAF_RANDSCALE: scale = LEAF_SCALE * Rand(1.0-LEAF_RANDSCALE, 1.0+LEAF_RANDSCALE)
else: scale = LEAF_SCALE * 1.0
@@ -912,7 +982,7 @@ class tree:
else: rand_vec = Vector( )
return Matrix([scale,0,0],[0,scale,0],[0,0,scale]).resize4x4() * (self.no + rand_vec).toTrackQuat('x', 'z').toMatrix().resize4x4() * TranslationMatrix(self.tailCo)
-
+ """
def distripute_seg_on_mesh(me__, face_group):
"""
add segment endpoints
@@ -941,7 +1011,7 @@ class tree:
# Dont need to return anything, added when created.
- def find_leaf_attach_point(seg, interior_points, twig_fill_rand_scale):
+ def set_seg_attach_point(seg, interior_points, twig_fill_rand_scale):
"""
Can only run on end nodes that have normals set
"""
@@ -952,7 +1022,7 @@ class tree:
for pt in interior_points:
# line from the point to the seg endpoint
- line_normal = seg.tailCo - pt.co
+ line_normal = seg.tailCo - pt.nextMidCo
l = line_normal.length
cross1 = CrossVecs( seg.no, line_normal )
@@ -969,19 +1039,33 @@ class tree:
if l < best_dist:
best_pt = pt
- best_co = pt.co.copy()
+ best_co = pt.nextMidCo
best_dist = l
-
+
# twig_fill_rand_scale
seg.headCo = best_co.copy()
if twig_fill_rand_scale:
seg_dir = seg.tailCo - seg.headCo
- seg_dir.length = seg_dir.length * ( 1.0 - Rand(0.0, twig_fill_rand_scale) )
+
+ seg_dir.length = seg_dir.length * ( 1.0 - (next_random_num(rnd)*twig_fill_rand_scale) )
seg.tailCo = seg.headCo + seg_dir
- seg.bpt = best_pt
+
+ if best_pt.childCount < 4:
+ # Watch this!!! adding a user before its attached and the branch is created!
+ # make sure if its not added later on, this isnt left added
+ best_pt.childCount += 1
+
+ # True/False denotes weather we try to connect to our parent branch
+ seg.bpt = (best_pt, True)
+ else:
+ seg.bpt = (best_pt, False)
+
+ return True
+
+
# END Twig code, next add them
@@ -1010,9 +1094,10 @@ class tree:
break # no need to check new branches are inside us
for pt in brch.bpoints:
- if self_tree.isPointInTwigBounds(pt.co, True): # selected_only
- interior_points.append(pt)
- interior_normal += pt.no * pt.radius
+ if pt.next and pt.childCount < 4: # cannot attach to the last points
+ if self_tree.isPointInTwigBounds(pt.co, True): # selected_only
+ interior_points.append(pt)
+ interior_normal += pt.no * pt.radius
segments_all[:] = []
segments_level[:] = []
@@ -1022,7 +1107,8 @@ class tree:
distripute_seg_on_mesh( self_tree.objectTwigBoundsMesh, face_group )
for seg in segments_level[0]: # only be zero segments
- find_leaf_attach_point(seg, interior_points, twig_fill_rand_scale)
+ # Warning, increments the child count for bpoints we attach to!!
+ set_seg_attach_point(seg, interior_points, twig_fill_rand_scale)
# Try sorting by other properties! this is ok for now
for segments_level_current in segments_level:
@@ -1041,25 +1127,20 @@ class tree:
for seg in segments_level[level+1]:
seg.calcBrothers()
- # Randomize scale recursively
- # This way sucks, just randomize starting lengths
- """
- if twig_fill_rand_scale != 0.0: # 0.0 - 1.0
- for seg in segments_all:
- #if seg.levelFromLeaf == 0:
- if 1:
- sca = 1.0 + Rand(-twig_fill_rand_scale, twig_fill_rand_scale)
- # print sca, 'SCALE'
- seg.scale(sca)
- """
-
for seg in segments_all:
if seg.parent == None:
seg.levelFromRoot = 0
seg.calcLevelFromRoot()
- for i, seg in enumerate(segments_all):
+ '''
+ for i, seg in enumerate(segments_all):
+ # Make a branch from this data!
+
+ brch = branch()
+ brch.type = BRANCH_TYPE_FILL
+ self_tree.branches_all.append(brch)
+ # ============================= do this per bez pair
# 1 is the base and 2 is the tail
#p1_h1 = seg.getHeadHandle()
@@ -1070,26 +1151,28 @@ class tree:
p2_co = seg.tailCo.copy()
#p2_h2 = seg.getTailHandle() # isnt used
- # Make a branch from this data!
-
- brch = branch()
- self_tree.branches_all.append(brch)
- # ============================= do this per bez pair
bez1_vec = (None, p1_co, p1_h2)
bez2_vec = (p2_h1, p2_co, None)
seg_root = seg.getRootSeg()
+
+ radius_root = seg_root.bpt.radius * twig_fill_radius_factor
+ # Clamp so the head is never smaller then the tail
+ if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min
+
if seg_root.levelFromLeaf:
# print seg_root.levelFromLeaf, seg.levelFromRoot
- WIDTH_STEP = ((seg_root.bpt.radius * twig_fill_radius_factor)-twig_fill_radius_min) / seg_root.levelFromLeaf
+ WIDTH_STEP = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1)
radius1 = twig_fill_radius_min + (WIDTH_STEP * (seg.levelFromLeaf+1))
- radius2 = twig_fill_radius_min + (WIDTH_STEP * seg.levelFromLeaf)
+ if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (WIDTH_STEP * seg.levelFromLeaf)
+ else: radius2 = twig_fill_radius_min
else:
- radius1 = seg_root.bpt.radius
+ radius1 = radius_root
radius2 = twig_fill_radius_min
+
points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2)
# dont apply self_tree.limbScale here! - its alredy done
@@ -1106,7 +1189,143 @@ class tree:
brch.calcData()
#
#preview_curve()
-
+ '''
+
+ for segments_level_current in reversed(segments_level):
+ for seg in segments_level_current:
+ if seg.used == False and (seg.parent == None or seg.parent.used == True):
+
+ # The root segment for this set of links.
+ # seg_root_linked = seg
+
+ brch = branch()
+ brch.type = BRANCH_TYPE_FILL
+ self_tree.branches_all.append(brch)
+
+ # Can we attach to a real branch?
+ if seg.parent == None:
+ if seg.bpt[1]: # we can do a real join into the attach point
+ brch.parent_pt = seg.bpt[0]
+ # brch.parent_pt.childCount # this has alredy changed from
+
+ '''
+ if seg.parent:
+ if seg.bpt[1] == 2:
+ #if seg.bpt[1]:
+ # print "Making Connection"
+ if seg.bpt[0] == None:
+ raise "Error"
+ if seg.bpt[1] != 2:
+ print seg.bpt[1]
+ raise "Error"
+
+ brch.parent_pt = seg.bpt[1]
+ brch.parent_pt.childCount += 1
+ if brch.parent_pt.childCount > 4:
+ raise "Aeeae"
+ print "\n\nM<aking Joint!!"
+ '''
+
+ if seg.parent:
+ sibling = seg.sibling()
+ if sibling.new_bpt:
+ if sibling.new_bpt.childCount < 4:
+ brch.parent_pt = sibling.new_bpt
+ brch.parent_pt.childCount +=1
+
+ # Go down the hierarhy
+ is_first = True
+ while seg != None:
+ seg.used = True
+
+ # ==============================================
+
+ #p1_h1 = seg.getHeadHandle()
+ p1_co = seg.headCo.copy()
+ p1_h2 = seg.getHeadHandle() # isnt used
+
+ p2_h1 = seg.getTailHandle()
+ p2_co = seg.tailCo.copy()
+ #p2_h2 = seg.getTailHandle() # isnt used
+
+
+ bez1_vec = (None, p1_co, p1_h2)
+ bez2_vec = (p2_h1, p2_co, None)
+
+ seg_root = seg.getRootSeg()
+
+ radius_root = seg_root.bpt[0].radius * twig_fill_radius_factor
+ # Clamp so the head is never smaller then the tail
+ if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min
+
+ if seg_root.levelFromLeaf:
+ # print seg_root.levelFromLeaf, seg.levelFromRoot
+ widthStep = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1)
+
+ radius1 = twig_fill_radius_min + (widthStep * (seg.levelFromLeaf+1))
+ if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (widthStep * seg.levelFromLeaf)
+ else: radius2 = twig_fill_radius_min
+ else:
+ radius1 = radius_root
+ radius2 = twig_fill_radius_min
+
+ points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2)
+
+
+ start_pointlist = 0
+
+ # This is like baseTrim, (remove the base points to make nice joins, accounting for radius of parent point)
+ # except we do it before the branch is made
+
+ if brch.parent_pt:
+ while len(pointlist) - start_pointlist > 2 and (Vector(pointlist[start_pointlist]) - brch.parent_pt.co).length < (brch.parent_pt.radius*2):
+ start_pointlist +=1
+
+ if is_first and brch.parent_pt:
+ # We need to move the base point to a place where it looks good on the parent branch
+ # to do this. move the first point, then remove the following points that look horrible (double back on themself)
+
+ no = Vector(pointlist[0]) - Vector(pointlist[-1])
+ no.length = brch.parent_pt.radius*2
+ pointlist[0] = list(Vector(pointlist[0]) - no)
+
+ """
+ pointlist[1][0] = (pointlist[0][0] + pointlist[2][0])/2.0
+ pointlist[1][1] = (pointlist[0][1] + pointlist[2][1])/2.0
+ pointlist[1][2] = (pointlist[0][2] + pointlist[2][2])/2.0
+
+ pointlist[2][0] = (pointlist[1][0] + pointlist[3][0])/2.0
+ pointlist[2][1] = (pointlist[1][1] + pointlist[3][1])/2.0
+ pointlist[2][2] = (pointlist[1][2] + pointlist[3][2])/2.0
+ """
+
+
+ # Done setting the start point
+
+
+ len_pointlist = len(pointlist)
+ if seg.children:
+ len_pointlist -= 1
+
+ # dont apply self_tree.limbScale here! - its alredy done
+ bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii]) for ii in xrange(start_pointlist, len_pointlist) ]
+ brch.bpoints.extend( bpoints )
+ # ==============================================
+
+ seg.new_bpt = bpoints[0]
+
+ if seg.children:
+ seg = seg.children[0]
+ else:
+ seg = None
+
+ is_first = False
+
+ # done adding points
+ brch.calcData()
+
+
+
def buildTwigs(self, twig_ratio, twig_select_mode, twig_select_factor):
@@ -1560,13 +1779,14 @@ class tree:
def toLeafMesh(self, mesh_leaf,\
leaf_branch_limit = 0.5,\
leaf_branch_limit_rand = 0.8,\
+ leaf_branch_limit_type_curve = False,\
+ leaf_branch_limit_type_grow = False,\
+ leaf_branch_limit_type_fill = False,\
leaf_size = 0.5,\
-
- leaf_fill=True,\
- leaf_fill_count=1000,\
- leaf_fill_ob_bounds=None,\
-
- leaf_dupliface=False,\
+ leaf_size_rand = 0.0,\
+ leaf_branch_density = 0.2,\
+ leaf_branch_dir_rand = 0.2,\
+ leaf_branch_angle = 75.0,\
leaf_dupliface_fromgroup=None,\
):
@@ -1576,252 +1796,110 @@ class tree:
Add to the existing mesh.
'''
+
# first collect stats, we want to know the average radius and total segments
#radius = [(pt.radius for pt in self.branches_all for pt in brch.bpoints for pt in brch.bpoints]
mesh_leaf = freshMesh(mesh_leaf)
self.mesh_leaf = mesh_leaf
- # Fill an object with leaves, kind of primitive but useful at times.
- if leaf_fill and leaf_fill_count and leaf_fill_ob_bounds:
-
- self.setLeafBounds(leaf_fill_ob_bounds)
-
- # Get bounds
-
- xmin = ymin = zmin = 10000000
- xmax = ymax = zmax =-10000000
-
- for v in self.objectLeafBoundsMesh.verts:
- x,y,z = tuple(v.co)
-
- if x < xmin: xmin = x
- if y < ymin: ymin = y
- if z < zmin: zmin = z
-
- if x > xmax: xmax = x
- if y > ymax: ymax = y
- if z > zmax: zmax = z
-
- verts_extend = []
- faces_extend = []
+ # elif leaf_dupliface and leaf_dupliface_fromgroup:
+
+ if leaf_dupliface_fromgroup:
- i = leaf_fill_count
- while i:
- # randomize branch values for leaves for now.
- vec = Vector(Rand(xmin, xmax), Rand(ymin, ymax), Rand(zmin, zmax))
-
- if self.objectLeafBoundsMesh.pointInside(vec):
- vec = (vec * self.objectLeafBoundsIMat) * self.objectCurveIMat
-
- # Find the closest branch
- brch_close, pt_close = self.closestBranchPt(vec)
-
- no = pt_close.co - vec
- #cross = CrossVecs(no, zup)
- cross = CrossVecs(no, pt_close.no)
- cross.length = leaf_size
-
- vec2 = vec - cross
- vec1 = vec + cross
-
- vec3 = vec - cross
- vec4 = vec + cross
-
-
- no_pt = pt_close.no.copy()
- no_pt.length = leaf_size
- vec3 += no_pt
- vec4 += no_pt
+ if leaf_branch_limit == 1.0:
+ max_radius = 1000000.0
+ else:
+ totpoints = 0
+ radius = 0.0
+ max_radius = 0.0
+ for brch in self.branches_all:
+ for pt in brch.bpoints:
+ radius += pt.radius
+ if pt.radius > max_radius:
+ max_radius = pt.radius
- '''
- no_pt = pt_close.no.copy()
- no_pt.length = leaf_size
- vec3 += no_pt
- vec4 += no_pt
- '''
+ #totpoints += len(brch.bpoints)
- faces_extend.append([len(verts_extend), len(verts_extend)+1, len(verts_extend)+2, len(verts_extend)+3])
- verts_extend.extend([vec1, vec2, vec3, vec4])
- i-=1
-
- self.mesh_leaf.verts.extend(verts_extend)
- self.mesh_leaf.faces.extend(faces_extend)
-
-
- elif leaf_dupliface and leaf_dupliface_fromgroup:
-
- totpoints = 0
- radius = 0.0
- max_radius = 0.0
- for brch in self.branches_all:
- for pt in brch.bpoints:
- radius += pt.radius
- if pt.radius > max_radius:
- max_radius = pt.radius
-
- #totpoints += len(brch.bpoints)
-
- radius_max = max_radius * leaf_branch_limit
-
+ radius_max = max_radius * leaf_branch_limit
verts_extend = []
faces_extend = []
- co1,co2,co3,co4 = Vector(),Vector(),Vector(),Vector()
+ co1 = Vector(0.0, -0.5, -0.5)
+ co2 = Vector(0.0, -0.5, 0.5)
+ co3 = Vector(0.0, 0.5, 0.5)
+ co4 = Vector(0.0, 0.5, -0.5)
+
+ if leaf_branch_dir_rand == 0.0:
+ rand_vec = Vector()
rnd_seed = [1.0] # could have seed as an input setting
for brch in self.branches_all:
# quick test, do we need leaves on this branch?
- if brch.bpoints[-1].radius > radius_max:
+ if leaf_branch_limit != 1.0 and brch.bpoints[-1].radius > radius_max:
continue
-
count = 0
for pt in brch.bpoints:
- if leaf_branch_limit_rand:
- # (-1 : +1) * leaf_branch_limit_rand
- rnd = 1 + (((next_random_num(rnd_seed) - 0.5) * 2 ) * leaf_branch_limit_rand)
+ if pt == brch.bpoints[0] or (leaf_branch_density != 1.0 and leaf_branch_density < next_random_num(rnd_seed)):
+ pass
else:
- rnd = 1.0
-
- if pt.childCount == 0 and (pt.radius * rnd) < radius_max:
- # Ok we can add a leaf here. set the co's correctly
- co1[:] = pt.co
- co2[:] = pt.co
- co3[:] = pt.co
- co4[:] = pt.co
-
-
- cross_leafdir = CrossVecs( zup, pt.no )
- cross_leafdir.length = (leaf_size/2) ### * pt.radius
-
-
- # Rotate the
- # Align this with the existing branch
- rotate = RotationMatrix( (next_random_num(rnd_seed)-0.5) * 360, 3, 'r', pt.no )
-
- cross_leafdir = cross_leafdir * rotate
-
- #cross_leafwidth = CrossVecs(pt.no, cross_leafdir)
-
- # Facing up
- cross_leafwidth_up = CrossVecs(zup, cross_leafdir).normalize() * leaf_size * pt.radius
- cross_leafwidth_aligned = pt.no
-
- #cross_leafwidth = (cross_leafwidth_up + cross_leafwidth_aligned)/2
- cross_leafwidth = cross_leafwidth_aligned
-
- cross_leafwidth.length = (leaf_size/2) ### *pt.radius
-
- # base width
- co1 += cross_leafdir
- co2 += cross_leafdir
- co3 -= cross_leafdir
- co4 -= cross_leafdir
-
- # base hight allong the branch
- co2 += cross_leafwidth
- co3 += cross_leafwidth
-
- co1 -= cross_leafwidth
- co4 -= cross_leafwidth
-
-
+ if leaf_branch_limit_rand:
+ # (-1 : +1) * leaf_branch_limit_rand
+ rnd = 1 + (((next_random_num(rnd_seed) - 0.5) * 2 ) * leaf_branch_limit_rand)
+ else:
+ rnd = 1.0
- i = len(verts_extend)
- faces_extend.append( (i,i+1,i+2,i+3) )
- verts_extend.extend([tuple(co1), tuple(co2), tuple(co3), tuple(co4)])
+ if pt.childCount == 0 and (leaf_branch_limit == 1.0 or (pt.radius * rnd) < radius_max):
+
+
+ leaf_size_tmp = leaf_size * (1.0-(next_random_num(rnd_seed)*leaf_size_rand))
+
+ if leaf_branch_dir_rand:
+ rand_vec = Vector(randuvec()) * leaf_branch_dir_rand
+ #else:
+ # rand_vec = Vector() # set above
+
+ # endpoints dont rotate
+ if pt.next != None:
+ cross1 = CrossVecs(zup, pt.no) # use this to offset the leaf later
+ cross2 = CrossVecs(cross1, pt.no)
+ if count %2:
+ mat_yaw = RotationMatrix(leaf_branch_angle, 4, 'r', cross2)
+ else:
+ mat_yaw = RotationMatrix(-leaf_branch_angle, 4, 'r', cross2)
+ #mat = mat * mat_yaw
+
+ if leaf_branch_dir_rand: leaf_no = (pt.no * mat_yaw) + rand_vec
+ else: leaf_no = (pt.no * mat_yaw)
+
+ # Correct upwards pointing from changing the yaw
+ #my_up = zup * mat
+
+ # correct leaf location for branch width
+ cross1.length = pt.radius/2
+ leaf_co = pt.co + cross1
+ else:
+ # no correction needed, we are at the end of the branch
+ if leaf_branch_dir_rand: leaf_co = pt.no + rand_vec
+ else: leaf_co = pt.no
+ leaf_co = pt.co
+
+ mat = Matrix([leaf_size_tmp,0,0],[0,leaf_size_tmp,0],[0,0,leaf_size_tmp]).resize4x4() * leaf_no.toTrackQuat('x', 'z').toMatrix().resize4x4()
+ mat = mat * TranslationMatrix(leaf_co)
+
+ i = len(verts_extend)
+ faces_extend.append( (i,i+1,i+2,i+3) )
+ verts_extend.extend([tuple(co4*mat), tuple(co3*mat), tuple(co2*mat), tuple(co1*mat)])
count += 1
+
# setup dupli's
- leaf_dupliface_fromgroup
-
- self.mesh_leaf.verts.extend(verts_extend)
- self.mesh_leaf.faces.extend(faces_extend)
-
-
-
-
-
-
-
-
- '''
- if 0:
- totpoints = 0
- radius = 0.0
- max_radius = 0.0
- for brch in self.branches_all:
- for pt in brch.bpoints:
- radius += pt.radius
- if pt.radius > max_radius:
- max_radius = pt.radius
-
- #totpoints += len(brch.bpoints)
-
- radius_max = max_radius * leaf_branch_limit
-
-
- verts_extend = []
- faces_extend = []
-
- co1,co2,co3,co4 = Vector(),Vector(),Vector(),Vector()
-
- for brch in self.branches_all:
-
- # quick test, do we need leaves on this branch?
- if brch.bpoints[-1].radius > radius_max:
- continue
-
- count = 0
- for pt in brch.bpoints:
- if pt.childCount == 0 and pt.radius < radius_max:
- # Ok we can add a leaf here. set the co's correctly
- co1[:] = pt.co
- co2[:] = pt.co
- co3[:] = pt.co
- co4[:] = pt.co
-
- cross_leafdir = CrossVecs( zup, pt.no )
- cross_leafdir.length = leaf_size
-
-
- #cross_leafwidth = CrossVecs(pt.no, cross_leafdir)
-
- # Facing up
- cross_leafwidth_up = CrossVecs(zup, cross_leafdir).normalize() * leaf_size
- cross_leafwidth_aligned = pt.no
-
- #cross_leafwidth = (cross_leafwidth_up + cross_leafwidth_aligned)/2
- cross_leafwidth = cross_leafwidth_aligned
-
- cross_leafwidth.length = leaf_size/2
-
- if count % 2:
- cross_leafwidth.negate()
- cross_leafdir.negate()
-
- co1 += cross_leafdir
- co2 += cross_leafdir
-
- co2 += cross_leafwidth
- co3 += cross_leafwidth
-
- co1 -= cross_leafwidth
- co4 -= cross_leafwidth
-
-
- i = len(verts_extend)
- faces_extend.append( (i,i+1,i+2,i+3) )
- verts_extend.extend([tuple(co1), tuple(co2), tuple(co3), tuple(co4)])
- count += 1
-
self.mesh_leaf.verts.extend(verts_extend)
self.mesh_leaf.faces.extend(faces_extend)
- '''
return self.mesh_leaf
@@ -2327,9 +2405,9 @@ class bpoint(object):
# cross = zup
# which works most of the time, but no verticle lines
- if AngleBetweenVecs(self.no, zup) > 1.0: cross = zup
- elif AngleBetweenVecs(self.no, yup) > 1.0: cross = yup
- else: cross = xup
+ if AngleBetweenVecsSafe(self.no, zup) > 1.0: cross = zup
+ elif AngleBetweenVecsSafe(self.no, yup) > 1.0: cross = yup
+ else: cross = xup
else:
cross = CrossVecs(self.prev.vecs[0], self.no)
@@ -2366,6 +2444,7 @@ class branch:
self.twig_count = 0 # count the number of twigs - so as to limit how many twigs a branch gets
# self.myindex = -1
### self.segment_spacing_scale = 1.0 # use this to scale up the spacing - so small twigs dont get WAY too many polys
+ self.type = None
def __repr__(self):
s = ''
@@ -2759,6 +2838,8 @@ class branch:
pt.calcNormal()
pt.calcNextMidCo()
+ # This is a bit dodgy - moving the branches around after placing can cause problems
+ """
def branchReJoin(self):
'''
Not needed but nice to run after collapsing incase segments moved a lot
@@ -2800,6 +2881,7 @@ class branch:
self.parent_pt.children[index] = self
self.parent_pt.childCount += 1
return
+ """
def checkPointList(self):
'''
@@ -2870,6 +2952,7 @@ class branch:
# Make the new branch
new_brch = branch()
+ new_brch.type = BRANCH_TYPE_GROWN
for i in xrange(len(cos1)):
new_brch.bpoints.append( bpoint(new_brch, (cos1[i]+cos2[i])*0.5, Vector(), (brch1.bpoints[i].radius*scales[0] + brch2.bpoints[i].radius*scales[1])/2) )
@@ -2962,15 +3045,15 @@ PREFS['twig_follow_y'] = Draw.Create(0.0)
PREFS['twig_follow_z'] = Draw.Create(0.0)
PREFS['do_leaf'] = Draw.Create(0)
-PREFS['leaf_fill'] = Draw.Create(1)
-PREFS['leaf_fill_count'] = Draw.Create(1000)
-PREFS['leaf_fill_ob_bounds'] = Draw.Create('')
PREFS['leaf_branch_limit'] = Draw.Create(0.25)
PREFS['leaf_branch_limit_rand'] = Draw.Create(0.1)
+PREFS['leaf_branch_density'] = Draw.Create(0.1)
+PREFS['leaf_branch_dir_rand'] = Draw.Create(0.2)
+PREFS['leaf_branch_angle'] = Draw.Create(75.0)
PREFS['leaf_size'] = Draw.Create(0.5)
+PREFS['leaf_size_rand'] = Draw.Create(0.0)
-PREFS['leaf_dupliface'] = Draw.Create(0)
PREFS['leaf_dupliface_fromgroup'] = Draw.Create('')
PREFS['do_variation'] = Draw.Create(0)
@@ -3227,23 +3310,21 @@ def buildTree(ob_curve, single=False):
ob_leaf.setMatrix(Matrix())
leaf_dupliface_fromgroup = getGroupFromName(PREFS['leaf_dupliface_fromgroup'].val)
-
- leaf_fill_ob_bounds = getObFromName(PREFS['leaf_fill_ob_bounds'].val)
mesh_leaf = t.toLeafMesh(mesh_leaf,\
leaf_branch_limit = PREFS['leaf_branch_limit'].val,\
leaf_branch_limit_rand = PREFS['leaf_branch_limit_rand'].val,\
leaf_size = PREFS['leaf_size'].val,\
+ leaf_size_rand = PREFS['leaf_size_rand'].val,\
- leaf_fill = PREFS['leaf_fill'].val,\
- leaf_fill_count = PREFS['leaf_fill_count'].val,\
- leaf_fill_ob_bounds = leaf_fill_ob_bounds,\
+ leaf_branch_density = PREFS['leaf_branch_density'].val,\
+ leaf_branch_dir_rand = PREFS['leaf_branch_dir_rand'].val,\
+ leaf_branch_angle = PREFS['leaf_branch_angle'].val,\
- leaf_dupliface = PREFS['leaf_dupliface'].val,\
leaf_dupliface_fromgroup = leaf_dupliface_fromgroup,\
)
- if PREFS['leaf_dupliface'].val and leaf_dupliface_fromgroup:
+ if leaf_dupliface_fromgroup:
ob_leaf.enableDupFaces = True
ob_leaf.enableDupFacesScale = True
for ob_group in leaf_dupliface_fromgroup.objects:
@@ -3528,7 +3609,7 @@ def gui():
xtmp = x
PREFS['twig_fill_radius_min'] = Draw.Number('Min Radius', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_min'].val, 0.0, 1.0, 'Radius at endpoints of all twigs'); xtmp += but_width*2;
- PREFS['twig_fill_radius_factor'] = Draw.Number('Inherit Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_factor'].val, 0.0, 1.0, 'What attaching to branches, scale the radius by this value for filled twigs'); xtmp += but_width*2;
+ PREFS['twig_fill_radius_factor'] = Draw.Number('Inherit Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_factor'].val, 0.0, 1.0, 'What attaching to branches, scale the radius by this value for filled twigs, 0.0 for fixed width twigs.'); xtmp += but_width*2;
y-=but_height
xtmp = x
@@ -3630,58 +3711,42 @@ def gui():
PREFS['do_leaf'] = Draw.Toggle('Generate Leaves',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_leaf'].val, 'Generate a separate leaf mesh'); xtmp += but_width*2;
if PREFS['do_leaf'].val:
- PREFS['leaf_size'] = Draw.Number('Size', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size'].val, 0.001, 10.0, 'size of the leaf'); xtmp += but_width*2;
-
- if PREFS['leaf_fill'].val == 0:
- but_width_tmp = but_width*2
- else:
- but_width_tmp = but_width*4
+ PREFS['leaf_dupliface_fromgroup'] = Draw.String('group: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_dupliface_fromgroup'].val, 64, 'Pick objects from this group to use as leaves', do_group_check); xtmp += but_width*2;
# ---------- ---------- ---------- ----------
y-=but_height
xtmp = x
-
- if PREFS['leaf_fill'].val == 1:
- but_width_tmp = but_width*2
- else:
- but_width_tmp = but_width*4
- PREFS['leaf_fill'] = Draw.Toggle('Fill Object', EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['leaf_fill'].val, 'Fill an object with leaves'); xtmp += but_width_tmp;
- if PREFS['leaf_fill'].val:
- PREFS['leaf_fill_ob_bounds'] = Draw.String('OB Bound: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_fill_ob_bounds'].val, 64, 'Fill this object with leaves', do_ob_check); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- PREFS['leaf_fill_count'] = Draw.Number('Fill #', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['leaf_fill_count'].val, 10, 100000, 'Number of leaves to fill in'); xtmp += but_width*4;
-
+ PREFS['leaf_size'] = Draw.Number('Size', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size'].val, 0.001, 10.0, 'size of the leaf'); xtmp += but_width*2;
+ PREFS['leaf_size_rand'] = Draw.Number('Randsize', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size_rand'].val, 0.0, 1.0, 'size of the leaf'); xtmp += but_width*2;
# ---------- ---------- ---------- ----------
y-=but_height
xtmp = x
+ # Dont use yet
+ PREFS['leaf_branch_limit'] = Draw.Number('Branch Limit', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit'].val, 0.0, 1.0, 'Maximum thichness where a branch can bare leaves, higher value to place leaves on bigger branches'); xtmp += but_width*2;
+ PREFS['leaf_branch_limit_rand'] = Draw.Number('Limit Random', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit_rand'].val, 0.0, 1.0, 'Randomize the allowed minimum branch width to place leaves'); xtmp += but_width*2;
+ # ---------- ---------- ---------- ----------
+ y-=but_height
+ xtmp = x
+ PREFS['leaf_branch_density'] = Draw.Number('Density', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['leaf_branch_density'].val, 0.0, 1.0, 'Chance each segment has of baring a leaf, use a high value for more leaves'); xtmp += but_width*4;
+ # ---------- ---------- ---------- ----------
+ y-=but_height
+ xtmp = x
- if PREFS['leaf_dupliface'].val == 1:
- but_width_tmp = but_width*2
- else:
- but_width_tmp = but_width*4
- PREFS['leaf_dupliface'] = Draw.Toggle('DupliLeaf', EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['leaf_dupliface'].val, 'Create a Dupliface mesh'); xtmp += but_width_tmp;
+ PREFS['leaf_branch_dir_rand'] = Draw.Number('Random Direction', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['leaf_branch_dir_rand'].val, 0.0, 1.0, 'Angle the leaves point away from the branch'); xtmp += but_width*4;
- if PREFS['leaf_dupliface'].val:
- PREFS['leaf_dupliface_fromgroup'] = Draw.String('group: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_dupliface_fromgroup'].val, 64, 'Pick objects from this group to use as leaves', do_group_check); xtmp += but_width*2;
-
- # ---------- ---------- ---------- ----------
- y-=but_height
- xtmp = x
-
- # Dont use yet
- PREFS['leaf_branch_limit'] = Draw.Number('Branch Limit', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit'].val, 0.0, 1.0, 'Maximum thichness where a branch can bare leaves'); xtmp += but_width*2;
- PREFS['leaf_branch_limit_rand'] = Draw.Number('Limit Random', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit_rand'].val, 0.0, 1.0, 'Randomize the starting of leaves'); xtmp += but_width*2;
+ # ---------- ---------- ---------- ----------
+ y-=but_height
+ xtmp = x
+ PREFS['leaf_branch_angle'] = Draw.Number('Angle From Branch', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['leaf_branch_angle'].val, 0.0, 90.0, 'Randomize the starting of leaves'); xtmp += but_width*4;
+
+
Blender.Draw.EndAlign()
y-=but_height+MARGIN