[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12623] trunk/blender/release/scripts/ wizard_curve2tree.py: initial leaf support (need to use in production, at the moment its really simple)
Campbell Barton
ideasman42 at gmail.com
Mon Nov 19 15:00:49 CET 2007
Revision: 12623
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12623
Author: campbellbarton
Date: 2007-11-19 15:00:48 +0100 (Mon, 19 Nov 2007)
Log Message:
-----------
initial leaf support (need to use in production, at the moment its really simple)
Option to generate variation's - This modifies the original shape to make a variation on the original.
Modified Paths:
--------------
trunk/blender/release/scripts/wizard_curve2tree.py
Modified: trunk/blender/release/scripts/wizard_curve2tree.py
===================================================================
--- trunk/blender/release/scripts/wizard_curve2tree.py 2007-11-19 10:49:12 UTC (rev 12622)
+++ trunk/blender/release/scripts/wizard_curve2tree.py 2007-11-19 14:00:48 UTC (rev 12623)
@@ -96,6 +96,14 @@
return mesh
+def getObFromName(name):
+ if name:
+ try: return bpy.data.objects[name]
+ except: return None
+ else:
+ return None
+
+
def closestVecIndex(vec, vecls):
best= -1
@@ -121,9 +129,16 @@
self.armature = None
self.objectCurve = None
self.objectCurveMat = None
+ self.objectCurveIMat = None
+
self.objectTwigBounds = None # use for twigs only at the moment.
self.objectTwigBoundsIMat = None
self.objectTwigBoundsMesh = None
+
+ self.objectLeafBounds = None
+ self.objectLeafBoundsIMat = None
+ self.objectLeafBoundsMesh = None
+
self.limbScale = 1.0
self.debug_objects = []
@@ -142,6 +157,7 @@
# Now calculate the normals
self.objectCurve = objectCurve
self.objectCurveMat = objectCurve.matrixWorld
+ self.objectCurveIMat = self.objectCurveMat.copy().invert()
curve = objectCurve.data
steps = curve.resolu # curve resolution
@@ -201,19 +217,41 @@
# Sort from big to small, so big branches get priority
self.branches_all.sort( key = lambda brch: -brch.bpoints[0].radius )
-
+
+
+ def closestBranchPt(self, co):
+ best_brch = None
+ best_pt = None
+ best_dist = 10000000000
+ for brch in self.branches_all:
+ for pt in brch.bpoints:
+ # if pt.inTwigBounds: # only find twigs, give different results for leaves
+ l = (pt.co-co).length
+ if l < best_dist:
+ best_dist = l
+ best_brch = brch
+ best_pt = pt
+ return best_brch, best_pt
+
def setTwigBounds(self, objectMesh):
self.objectTwigBounds = objectMesh
self.objectTwigBoundsMesh = objectMesh.getData(mesh=1)
self.objectTwigBoundsIMat = objectMesh.matrixWorld.copy().invert()
- #self.objectTwigBoundsIMat = objectMesh.matrixWorld.copy()
for brch in self.branches_all:
brch.calcTwigBounds(self)
+
+ def setLeafBounds(self, objectMesh):
+ self.objectLeafBounds = objectMesh
+ self.objectLeafBoundsMesh = objectMesh.getData(mesh=1)
+ self.objectLeafBoundsIMat = objectMesh.matrixWorld.copy().invert()
def isPointInTwigBounds(self, co):
return self.objectTwigBoundsMesh.pointInside(co * self.objectCurveMat * self.objectTwigBoundsIMat)
-
+
+ def isPointInLeafBounds(self, co):
+ return self.objectLeafBoundsMesh.pointInside(co * self.objectCurveMat * self.objectLeafBoundsIMat)
+
def resetTags(self, value):
for brch in self.branches_all:
brch.tag = value
@@ -223,6 +261,8 @@
connect_base_trim = 1.0,\
do_twigs = False,\
twig_ratio = 2.0,\
+ twig_select_mode = 0,\
+ twig_select_factor = 0.5,\
twig_scale = 0.8,\
twig_scale_width = 1.0,\
twig_random_orientation = 180,\
@@ -238,6 +278,11 @@
twig_follow_x=0.0,\
twig_follow_y=0.0,\
twig_follow_z=0.0,\
+ do_variation = 0,\
+ variation_seed = 1,\
+ variation_orientation = 0.0,\
+ variation_scale = 0.0,\
+
):
'''
build tree data - fromCurve must run first
@@ -284,7 +329,7 @@
children = [brch_child for brch_child in pt.children]
if children:
# This pt is one side of the segment, pt.next joins this segment.
- # calculate the median point the 2 segments would span
+ # calculate the median point the 2 segments would spanal
# Once this is done we need to adjust 2 things
# 1) move both segments up/down so they match the branches best.
# 2) set the spacing of the segments around the point.
@@ -300,9 +345,38 @@
brch.checkPointList()
'''
+ # Variations - use for making multiple versions of the same tree.
+ if do_variation:
+ irational_num = 22.0/7.0 # use to make the random number more odd
+ rnd = [variation_seed]
+ def next_random_num():
+ '''
+ return a random number between 0.0 and 1.0
+ '''
+
+ rnd[0] += (rnd[0] * irational_num) % 1
+ # prevent
+ if rnd[0] > 1000000:
+ rnd[0]-=1000000
+ return rnd[0] % 1
+
+ # Add children temporarily
+ for brch in self.branches_all:
+ if brch.parent_pt:
+ rnd_rot = ((next_random_num() * variation_orientation) - 0.5) * 720
+ mat_orientation = RotationMatrix(rnd_rot, 3, 'r', brch.parent_pt.no)
+ rnd_sca = 1 + ((next_random_num()-0.5)* variation_scale )
+ mat_scale = Matrix([rnd_sca,0,0],[0,rnd_sca,0],[0,0,rnd_sca])
+ # mat_orientation = RotationMatrix(0, 3, 'r', brch.parent_pt.no)
+ brch.transformRecursive(self, mat_scale * mat_orientation, brch.parent_pt.co)
+
# Important we so this with existing parent/child but before connecting and calculating verts.
-
if do_twigs:
+
+ # scale values down
+ twig_random_orientation= twig_random_orientation/360.0
+ twig_random_angle= twig_random_angle/360.0
+
irational_num = 22.0/7.0 # use to make the random number more odd
if twig_ob_bounds: # Only spawn twigs inside this mesh
@@ -311,7 +385,7 @@
if not twig_recursive:
twig_recursive_limit = 0
- self.buildTwigs(twig_ratio)
+ self.buildTwigs(twig_ratio, twig_select_mode, twig_select_factor)
branches_twig_attached = []
@@ -357,7 +431,6 @@
if twig_random_angle: rnd2 = (((irational_num * scale * 66666666) % 360) - 180) * twig_random_angle
else: rnd2 = 0.0
-
# Align this with the existing branch
angle = AngleBetweenVecs(zup, parent_pt.no)
cross = CrossVecs(zup, parent_pt.no)
@@ -397,8 +470,8 @@
no = Vector()
no.x += twig_follow_x
- no.x += twig_follow_y
- no.x += twig_follow_z
+ no.y += twig_follow_y
+ no.z += twig_follow_z
for i, pt in enumerate(brch_twig.bpoints):
if pt.prev:
@@ -529,7 +602,7 @@
for brch in self.branches_all:
brch.branchReJoin()
- def buildTwigs(self, twig_ratio=1.0):
+ def buildTwigs(self, twig_ratio, twig_select_mode, twig_select_factor):
ratio_int = int(len(self.branches_all) * twig_ratio)
if ratio_int == 0:
@@ -537,6 +610,20 @@
# So we only mix branches of similar lengths
branches_sorted = self.branches_all[:]
+
+ # Get the branches based on our selection method!
+ if twig_select_mode==0:
+ branches_sorted.sort( key = lambda brch: brch.getLength())
+ elif twig_select_mode==1:
+ branches_sorted.sort( key = lambda brch:-brch.getLength())
+ elif twig_select_mode==2:
+ branches_sorted.sort( key = lambda brch:brch.getStraightness())
+ elif twig_select_mode==3:
+ branches_sorted.sort( key = lambda brch:-brch.getStraightness())
+
+ factor_int = int(len(self.branches_all) * twig_select_factor)
+ branches_sorted[factor_int:] = [] # remove the last part of the list
+
branches_sorted.sort( key = lambda brch: len(brch.bpoints))
branches_new = []
@@ -967,7 +1054,8 @@
return self.mesh
- def toLeafMesh(self, mesh_leaf, leaf_branch_limit = 0.5, leaf_size = 0.5):
+ def toLeafMesh(self, mesh_leaf, leaf_branch_limit = 0.5, leaf_size = 0.5, leaf_fill=True, leaf_fill_count=1000, leaf_fill_ob_bounds=None):
+
'''
return a mesh with leaves seperate from the tree
@@ -979,81 +1067,152 @@
mesh_leaf = freshMesh(mesh_leaf)
self.mesh_leaf = mesh_leaf
- 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
+ # Fill an object with leaves, kind of primitive but useful at times.
+ if leaf_fill and leaf_fill_count and leaf_fill_ob_bounds:
- #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:
+ self.setLeafBounds(leaf_fill_ob_bounds)
- # quick test, do we need leaves on this branch?
- if brch.bpoints[-1].radius > radius_max:
- continue
+ # Get bounds
- 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
+ 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 = []
+
+ 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
- cross_leafdir = CrossVecs( zup, pt.no )
- cross_leafdir.length = leaf_size
-
+ # Find the closest branch
+ brch_close, pt_close = self.closestBranchPt(vec)
- #cross_leafwidth = CrossVecs(pt.no, cross_leafdir)
+ no = pt_close.co - vec
+ #cross = CrossVecs(no, zup)
+ cross = CrossVecs(no, pt_close.no)
+ cross.length = leaf_size
- # Facing up
- cross_leafwidth_up = CrossVecs(zup, cross_leafdir).normalize() * leaf_size
- cross_leafwidth_aligned = pt.no
+ vec2 = vec - cross
+ vec1 = vec + cross
- #cross_leafwidth = (cross_leafwidth_up + cross_leafwidth_aligned)/2
- cross_leafwidth = cross_leafwidth_aligned
+ vec3 = vec - cross
+ vec4 = vec + cross
- cross_leafwidth.length = leaf_size/2
- if count % 2:
- cross_leafwidth.negate()
- cross_leafdir.negate()
+ no_pt = pt_close.no.copy()
+ no_pt.length = leaf_size
+ vec3 += no_pt
+ vec4 += no_pt
- co1 += cross_leafdir
- co2 += cross_leafdir
+ '''
+ no_pt = pt_close.no.copy()
+ no_pt.length = leaf_size
+ vec3 += no_pt
+ vec4 += no_pt
+ '''
+ cross
- 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) )
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list