[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