[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