[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12573] trunk/blender/release/scripts/ wizard_curve2tree.py: Tree Wizard.

Campbell Barton ideasman42 at gmail.com
Tue Nov 13 00:19:33 CET 2007


Revision: 12573
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12573
Author:   campbellbarton
Date:     2007-11-13 00:19:33 +0100 (Tue, 13 Nov 2007)

Log Message:
-----------
Tree Wizard. 
'Twigs' - branch's added to the existing, made from blending existing branches into new ones.

Some user settings for scale, orientation randomness, number of twigs and recursive twigs.

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-12 21:54:09 UTC (rev 12572)
+++ trunk/blender/release/scripts/wizard_curve2tree.py	2007-11-12 23:19:33 UTC (rev 12573)
@@ -38,7 +38,7 @@
 
 import bpy
 import Blender
-from Blender.Mathutils import Vector, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix
+from Blender.Mathutils import Vector, Matrix, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
 from Blender.Geometry import ClosestPointOnLine
 
 GLOBALS = {}
@@ -98,6 +98,7 @@
 	def __init__(self):
 		self.branches_all =		[]
 		self.branches_root =	[]
+		self.branches_twigs =	[]
 		self.mesh = None
 		self.armature = None
 		self.object = None
@@ -172,21 +173,20 @@
 					bpoints.pop()
 				
 				brch.bpoints.extend(bpoints)
-		
+			
+			# Finalize once point data is there
+			brch.calcData()
+			
 		# Sort from big to small, so big branches get priority
 		self.branches_all.sort( key = lambda brch: -brch.bpoints[0].radius )
 		
-		for i, brch in enumerate(self.branches_all):
-			brch.calcPointLinkedList()
-			brch.calcPointExtras()
-			# brch.myindex = i
 		
 		
 	def resetTags(self, value):
 		for brch in self.branches_all:
 			brch.tag = value
 	
-	def buildConnections(self, sloppy=1.0, base_trim = 1.0):
+	def buildConnections(self, sloppy=1.0, base_trim = 1.0, do_twigs = False, twig_ratio=2.0, twig_scale=0.8, twig_random_orientation= 0.5, twig_recursive=True):
 		'''
 		build tree data - fromCurve must run first
 		
@@ -214,25 +214,11 @@
 						
 						# Check its in range, allow for a bit out - hense the sloppy
 						if dist < pt_best_j.radius * sloppy:
-							
-							# if 1)	dont remove the whole branch, maybe an option but later
-							# if 2)	we are alredy a parent, cant remove me now.... darn :/ not nice...
-							#		could do this properly but it would be slower and its a corner case.
-							#
-							# if 3)	this point is within the branch, remove it.
-							
-							
-							while	len(brch_i.bpoints)>2 and\
-									brch_i.bpoints[0].childCount == 0 and\
-									(brch_i.bpoints[0].co - pt_best_j.nextMidCo).length < pt_best_j.radius * base_trim:
-								
-								del brch_i.bpoints[0]
-								brch_i.bpoints[0].prev = None
-							
-							
 							brch_i.parent_pt = pt_best_j
 							pt_best_j.childCount += 1 # dont remove me
 							
+							brch_i.baseTrim(base_trim)
+							
 							'''
 							if pt_best_j.childCount>4:
 								raise "ERROR"
@@ -263,6 +249,100 @@
 			brch.checkPointList()
 		'''
 		
+		# Important we so this with existing parent/child but before connecting and calculating verts.
+		
+		if do_twigs:
+			self.buildTwigs(twig_ratio)
+			
+			branches_twig_attached = []
+			
+			# This wont add all! :/
+			brch_twig_index = 0
+			brch_twig_index_LAST = -1 # use this to prevent in inf loop, since its possible we cant place every branch
+			while brch_twig_index < len(self.branches_twigs) and brch_twig_index_LAST != brch_twig_index:
+				###print "While"
+				### print brch_twig_index, len(self.branches_twigs) # if this dosnt change, quit the while
+				
+				brch_twig_index_LAST = brch_twig_index
+				
+				# new twigs have been added, recalculate
+				branches_twig_sort = [(brch.bestTwigSegment(), brch) for brch in self.branches_all]
+				branches_twig_sort.sort() # this will sort the branches with best braches for adding twigs to at the start of the list
+				
+				for twig_data, brch_parent in branches_twig_sort:
+					twig_pt_index = twig_data[1]
+					
+					if twig_pt_index != -1:
+						
+						###print "\tFor",
+						###print brch_twig_index, len(self.branches_twigs)
+						if brch_twig_index >= len(self.branches_twigs):
+							break
+						
+						#print "twig"
+						
+						brch_twig = self.branches_twigs[brch_twig_index]
+						
+						
+						parent_pt = brch_parent.bpoints[twig_pt_index]
+						brch_twig.parent_pt = parent_pt
+						parent_pt.childCount += 1
+						
+						#angle = brch_parent.getParentAngle()
+						
+						# Align this with the existing branch
+						angle = AngleBetweenVecs(zup, parent_pt.no)
+						cross = CrossVecs(zup, parent_pt.no)
+						mat_align = RotationMatrix(angle, 3, 'r', cross)
+						# brch_twig.transform(mat)
+						
+						# Use the bend on the point to work out which way to make the branch point!
+						if parent_pt.prev:	cross = CrossVecs(parent_pt.no, parent_pt.prev.no - parent_pt.no)
+						else:				cross = CrossVecs(parent_pt.no, parent_pt.next.no - parent_pt.no)
+						
+						if parent_pt.branch.parent_pt:
+							angle = AngleBetweenVecs(parent_pt.branch.parent_pt.no, parent_pt.no)
+						else:
+							# Should add a UI for this... only happens when twigs come off a root branch
+							angle = 66
+						
+						mat_branch_angle = RotationMatrix(angle, 3, 'r', cross)
+						
+						# Scale this twig using this way...
+						# The size of the parent, scaled by the parent point's radius,
+						# ...compared to the parent branch;s root point radius.
+						# Also take into account the length of the parent branch
+						scale = twig_scale * (parent_pt.branch.bpoints[0].radius / brch_twig.bpoints[0].radius) * (parent_pt.radius / parent_pt.branch.bpoints[0].radius)
+						mat_scale = Matrix([scale,0,0],[0,scale,0],[0,0,scale])
+						
+						# Random orientation
+						
+						rnd = Rand(0, twig_random_orientation)
+						
+						mat_orientation = RotationMatrix(rnd*180, 3, 'r', parent_pt.no)
+						
+						brch_twig.transform(mat_scale * mat_branch_angle * mat_align * mat_orientation, parent_pt.co)
+						
+						#print "Attempting to trim base"
+						brch_twig.baseTrim(base_trim)
+						
+						# Make sure this dosnt mess up anything else
+						
+						brch_twig_index += 1
+						
+						# Add to the branches
+						#self.branches_all.append(brch_twig)
+						branches_twig_attached.append(brch_twig)
+				
+				# Watch This! - move 1 tab down for no recursive twigs
+				if twig_recursive:
+					self.branches_all.extend(branches_twig_attached)
+					branches_twig_attached = []
+			
+			if not twig_recursive:
+				self.branches_all.extend(branches_twig_attached)
+				branches_twig_attached = []
+		
 		### self.branches_all.sort( key = lambda brch: brch.parent_pt != None )
 		
 		# Calc points with dependancies
@@ -330,6 +410,34 @@
 		for brch in self.branches_all:
 			brch.branchReJoin()
 	
+	def buildTwigs(self, twig_ratio=1.0):
+		
+		ratio_int = int(len(self.branches_all) * twig_ratio)
+		if ratio_int == 0:
+			return
+		
+		# So we only mix branches of similar lengths
+		branches_sorted = self.branches_all[:]
+		branches_sorted.sort( key = lambda brch: len(brch.bpoints))
+		
+		branches_new = []
+		#for i in xrange(ratio_int):
+		tot_twigs = 0
+		
+		step = 1
+		while tot_twigs < ratio_int and step < len(branches_sorted):
+			# Make branches from the existing
+			for j in xrange(step, len(branches_sorted)):
+				brch = branches_sorted[j-step].mixToNew(branches_sorted[j], None)
+				branches_new.append( brch )
+				tot_twigs +=1
+				
+				if tot_twigs > ratio_int:
+					break
+		
+		### print "TwigCount", len(branches_new), ratio_int
+		
+		self.branches_twigs = branches_new
 	
 	def toDebugDisplay(self):
 		'''
@@ -744,7 +852,7 @@
 			
 			#(%s.evaluate((b.Get("curframe")*%.3f,0,0)).w-0.5)*%.3f
 		
-		
+xyzup = Vector(1,1,1).normalize()
 xup = Vector(1,0,0)
 yup = Vector(0,1,0)
 zup = Vector(0,0,1)
@@ -1046,7 +1154,7 @@
 		use for aurienting the sides of a quad to meet a branch that stems from here...
 		'''
 		
-		mat = Blender.Mathutils.RotationMatrix(angle, 3, 'r', self.no)
+		mat = RotationMatrix(angle, 3, 'r', self.no)
 		for i in xrange(4):
 			self.vecs[i] = self.vecs[i] * mat
 	
@@ -1108,7 +1216,7 @@
 		
 		self.vecs[0] = Blender.Mathutils.CrossVecs(self.no, cross)
 		self.vecs[0].length = self.radius
-		mat = Blender.Mathutils.RotationMatrix(90, 3, 'r', self.no)
+		mat = RotationMatrix(90, 3, 'r', self.no)
 		self.vecs[1] = self.vecs[0] * mat
 		self.vecs[2] = self.vecs[1] * mat
 		self.vecs[3] = self.vecs[2] * mat
@@ -1128,7 +1236,8 @@
 		self.parent_pt = None
 		self.tag = False # have we calculated our points
 		self.face_cap = None
-		
+		self.length = -1
+		# self.totchildren = 0
 		# Bones per branch
 		self.bones = []
 		# self.myindex = -1
@@ -1140,6 +1249,37 @@
 		for pt in brch.bpoints:
 			s += str(self.pt)
 	
+	def getNormal(self):
+		return (self.bpoints[-1].co - self.bpoints[0].co).normalize()
+	
+	def getParentAngle(self):
+		if self.parent_pt:
+			return AngleBetweenVecs(self.parent_pt.no, self.bpoints[0].no )
+		else:
+			return 45.0
+	
+	def getParentRadiusRatio(self):
+		if self.parent_pt:
+			return self.bpoints[0].radius / self.parent_pt.radius
+		else:
+			return 0.8
+	
+		
+	
+	def getLength(self):
+		return (self.bpoints[0].co - self.bpoints[-1].co).length
+	'''
+	def calcTotChildren(self):
+		for pt in self.bpoints:
+			self.totchildren += pt.childCount
+	'''
+	def calcData(self):
+		'''
+		Finalize once point data is there
+		'''
+		self.calcPointLinkedList()
+		self.calcPointExtras()
+	
 	def calcPointLinkedList(self):
 		for i in xrange(1, len(self.bpoints)-1):
 			self.bpoints[i].next = self.bpoints[i+1]
@@ -1153,6 +1293,20 @@
 			pt.calcNormal()
 			pt.calcNextMidCo()		
 	
+	def baseTrim(self, base_trim):
+		# if 1)	dont remove the whole branch, maybe an option but later
+		# if 2)	we are alredy a parent, cant remove me now.... darn :/ not nice...
+		#		could do this properly but it would be slower and its a corner case.
+		#
+		# if 3)	this point is within the branch, remove it.
+		
+		while	len(self.bpoints)>2 and\
+				self.bpoints[0].childCount == 0 and\
+				(self.bpoints[0].co - self.parent_pt.nextMidCo).length < self.parent_pt.radius * base_trim:
+			
+			del self.bpoints[0]
+			self.bpoints[0].prev = None
+	
 	def getParentBranch(self):
 		if not self.parent_pt:
 			return None
@@ -1234,6 +1388,70 @@
 		
 		return False
 	
+	def transform(self, mat, loc=None):
+		scale = (xyzup * mat).length
+		for pt in self.bpoints:
+			if loc:
+				pt.co = (pt.co * mat) + loc
+			else:
+				pt.co = pt.co * mat
+			pt.radius *= scale
+		
+		for pt in self.bpoints:
+			self.calcPointExtras()
+	
+	def translate(self, co):
+		'''
+		Simply move the twig on the branch
+		'''
+		ofs = self.bpoints[0].co-co
+		for pt in self.bpoints:
+			pt.co -= ofs
+	
+	def bestTwigSegment(self):
+		'''

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list