[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12671] trunk/blender/release/scripts/ wizard_curve2tree.py: new twig type that gives more even results - " Fill Twigs" option

Campbell Barton ideasman42 at gmail.com
Sun Nov 25 21:49:40 CET 2007


Revision: 12671
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12671
Author:   campbellbarton
Date:     2007-11-25 21:49:38 +0100 (Sun, 25 Nov 2007)

Log Message:
-----------
new twig type that gives more even results - "Fill Twigs" option

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-25 20:12:54 UTC (rev 12670)
+++ trunk/blender/release/scripts/wizard_curve2tree.py	2007-11-25 20:49:38 UTC (rev 12671)
@@ -38,6 +38,7 @@
 
 import bpy
 import Blender
+import BPyMesh
 from Blender.Mathutils import Vector, Matrix, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
 from Blender.Geometry import ClosestPointOnLine
 
@@ -73,7 +74,16 @@
 			q1+= q2
 			q2+= q3;
 
+def points_from_bezier_seg(steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2):
+	
+	# x,y,z,axis
+	for ii in (0,1,2):
+		forward_diff_bezier(bez1_vec[1][ii], bez1_vec[2][ii],  bez2_vec[0][ii], bez2_vec[1][ii], pointlist, steps, ii)
+	
+	# radius - no axis, Copied from blenders BBone roll interpolation.
+	forward_diff_bezier(radius1, radius1 + 0.390464*(radius2-radius1), radius2 - 0.390464*(radius2-radius1),	radius2,	radlist, steps, None)
 
+
 def debug_pt(co):
 	Blender.Window.SetCursorPos(tuple(co))
 	Blender.Window.RedrawAll()
@@ -158,6 +168,7 @@
 		self.limbScale = 1.0
 		
 		self.debug_objects = []
+		self.steps = 6 # defalt, curve overwrites
 	
 	def __repr__(self):
 		s = ''
@@ -175,7 +186,7 @@
 		self.objectCurveMat = objectCurve.matrixWorld
 		self.objectCurveIMat = self.objectCurveMat.copy().invert()
 		curve = objectCurve.data
-		steps = curve.resolu # curve resolution
+		self.steps = curve.resolu # curve resolution
 		
 		# Set the curve object scale
 		if curve.bevob:
@@ -188,8 +199,8 @@
 			
 		# forward_diff_bezier will fill in the blanks
 		# nice we can reuse these for every curve segment :)
-		pointlist = [[None, None, None] for i in xrange(steps+1)]
-		radlist = [ None for i in xrange(steps+1) ]
+		pointlist = [[None, None, None] for i in xrange(self.steps+1)]
+		radlist = [ None for i in xrange(self.steps+1) ]
 
 
 		for spline in curve:
@@ -209,19 +220,7 @@
 			for i in xrange(1, len(bez_list)):
 				bez1 = bez_list[i-1]
 				bez2 = bez_list[i]
-				bez1_vec = bez1.vec
-				bez2_vec = bez2.vec
-				
-				radius1 = bez1.radius
-				radius2 = bez2.radius
-				
-				# x,y,z,axis
-				for ii in (0,1,2):
-					forward_diff_bezier(bez1_vec[1][ii], bez1_vec[2][ii],  bez2_vec[0][ii], bez2_vec[1][ii], pointlist, steps, ii)
-				
-				# radius - no axis, Copied from blenders BBone roll interpolation.
-				forward_diff_bezier(radius1, radius1 + 0.390464*(radius2-radius1), radius2 - 0.390464*(radius2-radius1),	radius2,	radlist, steps, None)
-				
+				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
@@ -264,11 +263,11 @@
 		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 isPointInTwigBounds(self, co, selected_only=False):
+		return self.objectTwigBoundsMesh.pointInside(co * self.objectCurveMat * self.objectTwigBoundsIMat, selected_only)
 
-	def isPointInLeafBounds(self, co):
-		return self.objectLeafBoundsMesh.pointInside(co * self.objectCurveMat * self.objectLeafBoundsIMat)
+	def isPointInLeafBounds(self, co, selected_only=False):
+		return self.objectLeafBoundsMesh.pointInside(co * self.objectCurveMat * self.objectLeafBoundsIMat, selected_only)
 
 	def resetTags(self, value):
 		for brch in self.branches_all:
@@ -300,11 +299,21 @@
 							variation_seed = 1,\
 							variation_orientation = 0.0,\
 							variation_scale = 0.0,\
+							do_twigs_fill = 0,\
+							twig_fill_levels=4,\
+							twig_fill_rand_scale=0.0,\
+							twig_fill_fork_angle_max=60.0,\
+							twig_fill_radius_min=0.1,\
+							twig_fill_radius_factor=0.75,\
+							twig_fill_shape_type=0,\
+							twig_fill_shape_rand=0.0,\
+							twig_fill_shape_power=0.3,\
 						):
 		'''
 		build tree data - fromCurve must run first
 		'''
 		
+		
 		# Sort the branchs by the first radius, so big branchs get joins first
 		### self.branches_all.sort( key = lambda brch: brch.bpoints[0].radius )
 		
@@ -377,6 +386,9 @@
 					# mat_orientation = RotationMatrix(0, 3, 'r', brch.parent_pt.no)
 					brch.transformRecursive(self, mat_scale * mat_orientation, brch.parent_pt.co)
 		
+		if (do_twigs or do_twigs_fill) and twig_ob_bounds: # Only spawn twigs inside this mesh
+			self.setTwigBounds(twig_ob_bounds)
+		
 		# Important we so this with existing parent/child but before connecting and calculating verts.
 		if do_twigs:
 			
@@ -386,9 +398,6 @@
 			
 			irational_num = 22.0/7.0 # use to make the random number more odd
 			
-			if twig_ob_bounds: # Only spawn twigs inside this mesh
-				self.setTwigBounds(twig_ob_bounds)
-			
 			if not twig_recursive:
 				twig_recursive_limit = 0
 			
@@ -542,6 +551,19 @@
 				self.branches_all.extend(branches_twig_attached)
 				branches_twig_attached = []
 		
+		
+		if do_twigs_fill and twig_ob_bounds:
+			self.twigFill(\
+				twig_fill_levels,\
+				twig_fill_rand_scale,\
+				twig_fill_fork_angle_max,\
+				twig_fill_radius_min,\
+				twig_fill_radius_factor,\
+				twig_fill_shape_type,\
+				twig_fill_shape_rand,\
+				twig_fill_shape_power,\
+			)
+		
 		### self.branches_all.sort( key = lambda brch: brch.parent_pt != None )
 		
 		# Calc points with dependancies
@@ -610,6 +632,482 @@
 		for brch in self.branches_all:
 			brch.branchReJoin()
 		'''
+	
+	def twigFill(self_tree,\
+			twig_fill_levels,\
+			twig_fill_rand_scale,\
+			twig_fill_fork_angle_max,\
+			twig_fill_radius_min,\
+			twig_fill_radius_factor,\
+			twig_fill_shape_type,\
+			twig_fill_shape_rand,\
+			twig_fill_shape_power,\
+		):
+		'''
+		Fill with twigs, this function uses its own class 'segment'
+		
+		twig_fill_shape_type;
+			0 - no child smoothing
+			1 - smooth one child
+			2 - smooth both children
+		
+		'''
+		
+		segments_all = []
+		segments_level = []
+		
+		# Only for testing
+		def preview_curve():
+			TWIG_WIDTH_MAX = 1.0
+			TWIG_WIDTH_MIN = 0.1
+			cu = bpy.data.curves["cu"]
+			# remove all curves
+			while len(cu):
+				del cu[0]
+			# return
+			
+			cu.setFlag(1)
+			cu.ext2 = 0.01
+			
+			WIDTH_STEP = (TWIG_WIDTH_MAX-TWIG_WIDTH_MIN) / twig_fill_levels
+			
+			for i, seg in enumerate(segments_all):
+				
+				# 1 is the base and 2 is the tail
+				
+				p1_h2 = seg.getHeadHandle() # isnt used
+				p1_co = seg.headCo
+				p1_h1 = seg.getHeadHandle()
+				
+				p2_h1 = seg.getTailHandle()
+				
+				p2_co = seg.tailCo
+				p2_h2 = seg.tailCo # isnt used
+				
+				bez1 = Blender.BezTriple.New([ p1_h1[0], p1_h1[1], p1_h1[2], p1_co[0], p1_co[1], p1_co[2], p1_h2[0], p1_h2[1], p1_h2[2] ])
+				bez2 = Blender.BezTriple.New([ p2_h1[0], p2_h1[1], p2_h1[2], p2_co[0], p2_co[1], p2_co[2], p2_h2[0], p2_h2[1], p2_h2[2] ])
+				bez1.handleTypes = bez2.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE]
+				
+				bez1.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * (seg.levelFromLeaf+1))
+				bez2.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * seg.levelFromLeaf)
+				
+				cunurb = cu.appendNurb(bez1)
+				cunurb.append(bez2)
+				
+				# This sucks
+				for bez in cunurb:
+					bez.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE]
+			
+			### cc = sce.objects.new( cu )
+			cu.update()
+		
+		
+		def mergeCo(parentCo, ch1Co, ch2Co, twig_fill_shape_rand):
+			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)
+				wtot = w1+w2+w3
+				w1=w1/wtot
+				w2=w2/wtot
+				w3=w3/wtot
+				
+				# return (parentCo*w1 + ch1Co*w2 + ch2Co*w2)
+				co1 = (parentCo * w1)	+ (ch1Co * (1.0-w1))
+				co2 = (ch1Co * w2)		+ (ch2Co * (1.0-w2))
+				co3 = (ch2Co * w3)		+ (parentCo * (1.0-w3))
+				
+				return (co1 + co2 + co3) / 3.0
+				
+				
+		
+		class segment:
+			def __init__(self, level):
+				self.headCo = Vector()
+				self.tailCo = Vector()
+				self.parent = None
+				self.mergeCount = 0
+				self.levelFromLeaf = level # how far we are from the leaf in levels
+				self.levelFromRoot = -1 # set later, assume root bone
+				self.children = []
+				segments_all.append(self)
+				
+				if level >= len(segments_level):	segments_level.append([self])
+				else:								segments_level[level].append(self)
+				
+				self.brothers = []
+				self.no = Vector() # only endpoints have these
+				self.id = len(segments_all)
+				self.bpt = None # branch point for root segs only
+				
+			def getHeadHandle(self):
+				"""
+				For Bezier only
+				"""
+				
+				if not self.parent:
+					return self.headCo
+				
+				if twig_fill_shape_type == 0: # no smoothing
+					return self.headCo
+				elif twig_fill_shape_type == 1:
+					if self.parent.children[1] == self:
+						return self.headCo
+				# 2 - always do both
+				
+				
+				# Y shape with curve? optional
+				
+				# we have a parent but it has no handle direction, easier
+				if not self.parent.parent:	no = self.parent.headCo - self.parent.tailCo
+				else:						no = self.parent.parent.headCo-self.parent.tailCo
+				
+				no.length =  self.getLength() * twig_fill_shape_power
+				# Ok we have to account for the parents handle
+				return self.headCo - no
+				# return self.headCo - Vector(1, 0,0)
+			
+			def getTailHandle(self):
+				"""
+				For Bezier only
+				"""
+				if self.parent:
+					no = self.parent.headCo-self.tailCo
+					no.length = self.getLength() * twig_fill_shape_power
+					return self.tailCo + no
+				else:
+					return self.tailCo # isnt used
+			
+			def getRootSeg(self):
+				seg = self
+				while seg.parent:
+					seg = seg.parent
+				
+				return seg
+			
+			def calcBrothers(self):
+				# Run on children first
+				self.brothers.extend( \
+					[seg_child_sibling.parent \
+						for seg_child in self.children \
+						for seg_child_sibling in seg_child.brothers \
+						if seg_child_sibling.parent not in (self, None)]\
+					)
+					#print self.brothers
+			
+			def calcLevelFromRoot(self):
+				if self.parent:

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list