Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijenstina <lijenstina@gmail.com>2017-04-08 01:24:05 +0300
committerlijenstina <lijenstina@gmail.com>2017-04-08 01:24:05 +0300
commit2aa13cb25adfe95bbc57f4c7442c91f020df5f2d (patch)
tree1c69c0adba1e4fc2105167bc040e32a31f44ec5e /add_curve_sapling
parent9bc76f9902e756c149695b2b3d86ebe2d690ae65 (diff)
Sapling Tree Gen: Cleanup, fix warning
Bumped version to 0.3.3 Fix star imports Pep8 cleanup Fix RNA Warning: Current value "0" matches no enum The EnumProperty function were passed an empty list if there were no adequate objects in the scene
Diffstat (limited to 'add_curve_sapling')
-rw-r--r--add_curve_sapling/__init__.py788
-rw-r--r--add_curve_sapling/utils.py841
2 files changed, 988 insertions, 641 deletions
diff --git a/add_curve_sapling/__init__.py b/add_curve_sapling/__init__.py
index fd6f5e97..1c91c1c7 100644
--- a/add_curve_sapling/__init__.py
+++ b/add_curve_sapling/__init__.py
@@ -1,4 +1,4 @@
-#====================== BEGIN GPL LICENSE BLOCK ======================
+# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -14,18 +14,18 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
-#======================= END GPL LICENSE BLOCK ========================
+# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Sapling Tree Gen",
"author": "Andrew Hale (TrumanBlending), Aaron Buchler",
- "version": (0, 3, 2),
+ "version": (0, 3, 3),
"blender": (2, 77, 0),
"location": "View3D > Add > Curve",
"description": ("Adds a parametric tree. The method is presented by "
"Jason Weber & Joseph Penn in their paper 'Creation and Rendering of "
- "Realistic Trees'."),
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
+ "Realistic Trees'"),
+ "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Curve/Sapling_Tree",
"category": "Add Curve"}
@@ -40,14 +40,21 @@ import time
import os
import ast
-#import cProfile
-
-from mathutils import *
-from math import pi, sin, degrees, radians, atan2, copysign
-from random import random, uniform, seed, choice, getstate, setstate
-from bpy.props import *
-
-from add_curve_sapling.utils import *
+# import cProfile
+
+from bpy.types import (
+ Operator,
+ Menu,
+ )
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ IntProperty,
+ IntVectorProperty,
+ StringProperty,
+ )
useSet = False
@@ -97,16 +104,17 @@ branchmodes = [("original", "Original", "rotate around each branch"),
("rotate", "Rotate", "evenly distribute branches to point outward from center of tree"),
("random", "Random", "choose random point")]
+
def getPresetpath():
"""Support user defined scripts directory
Find the first ocurrence of add_curve_sapling/presets in possible script paths
and return it as preset path"""
- #presetpath = ""
- #for p in bpy.utils.script_paths():
+ # presetpath = ""
+ # for p in bpy.utils.script_paths():
# presetpath = os.path.join(p, 'addons', 'add_curve_sapling_3', 'presets')
# if os.path.exists(presetpath):
# break
- #return presetpath
+ # return presetpath
# why not just do this
script_file = os.path.realpath(__file__)
@@ -114,6 +122,7 @@ def getPresetpath():
directory = os.path.join(directory, "presets")
return directory
+
def getPresetpaths():
"""Return paths for both local and user preset folders"""
userDir = os.path.join(bpy.utils.script_path_user(), 'presets', 'operator', 'add_curve_sapling')
@@ -129,7 +138,8 @@ def getPresetpaths():
return (localDir, userDir)
-class ExportData(bpy.types.Operator):
+
+class ExportData(Operator):
"""This operator handles writing presets to file"""
bl_idname = 'sapling.exportdata'
bl_label = 'Export Preset'
@@ -139,24 +149,24 @@ class ExportData(bpy.types.Operator):
def execute(self, context):
# Unpack some data from the input
data, filename, overwrite = eval(self.data)
-
-# try:
-# # Check whether the file exists by trying to open it.
-# f = open(os.path.join(getPresetpaths()[1], filename + '.py'), 'r')
-# f.close()
-# # If it exists then report an error
-# self.report({'ERROR_INVALID_INPUT'}, 'Preset Already Exists')
-# return {'CANCELLED'}
-# except IOError:
-# if data:
-# # If it doesn't exist, create the file with the required data
-# f = open(os.path.join(getPresetpaths()[1], filename + '.py'), 'w')
-# f.write(data)
-# f.close()
-# return {'FINISHED'}
-# else:
-# return {'CANCELLED'}
-
+ """
+ try:
+ # Check whether the file exists by trying to open it.
+ f = open(os.path.join(getPresetpaths()[1], filename + '.py'), 'r')
+ f.close()
+ # If it exists then report an error
+ self.report({'ERROR_INVALID_INPUT'}, 'Preset Already Exists')
+ return {'CANCELLED'}
+ except IOError:
+ if data:
+ # If it doesn't exist, create the file with the required data
+ f = open(os.path.join(getPresetpaths()[1], filename + '.py'), 'w')
+ f.write(data)
+ f.close()
+ return {'FINISHED'}
+ else:
+ return {'CANCELLED'}
+ """
fpath1 = os.path.join(getPresetpaths()[0], filename + '.py')
fpath2 = os.path.join(getPresetpaths()[1], filename + '.py')
@@ -165,7 +175,7 @@ class ExportData(bpy.types.Operator):
self.report({'ERROR_INVALID_INPUT'}, 'Can\'t have same name as built-in preset')
return {'CANCELLED'}
elif (not os.path.exists(fpath2)) or (os.path.exists(fpath2) and overwrite):
- #if (it does not exist) or (exists and overwrite) then write file
+ # if (it does not exist) or (exists and overwrite) then write file
if data:
# If it doesn't exist, create the file with the required data
f = open(os.path.join(getPresetpaths()[1], filename + '.py'), 'w')
@@ -179,10 +189,11 @@ class ExportData(bpy.types.Operator):
self.report({'ERROR_INVALID_INPUT'}, 'Preset Already Exists')
return {'CANCELLED'}
-class ImportData(bpy.types.Operator):
+
+class ImportData(Operator):
"""This operator handles importing existing presets"""
- bl_idname = 'sapling.importdata'
- bl_label = 'Import Preset'
+ bl_idname = "sapling.importdata"
+ bl_label = "Import Preset"
filename = StringProperty()
@@ -196,15 +207,15 @@ class ImportData(bpy.types.Operator):
f = open(os.path.join(getPresetpaths()[1], self.filename), 'r')
settings = f.readline()
f.close()
- #print(settings)
+ # print(settings)
settings = ast.literal_eval(settings)
- #use old attractup
+ # use old attractup
if type(settings['attractUp']) == float:
atr = settings['attractUp']
settings['attractUp'] = [0, 0, atr, atr]
- #use old leaf rotations
+ # use old leaf rotations
if 'leafDownAngle' not in settings:
l = settings['levels']
settings['leafDownAngle'] = settings['downAngle'][min(l, 3)]
@@ -212,14 +223,15 @@ class ImportData(bpy.types.Operator):
settings['leafRotate'] = settings['rotate'][min(l, 3)]
settings['leafRotateV'] = settings['rotateV'][min(l, 3)]
- #zero leaf bend
+ # zero leaf bend
settings['bend'] = 0
# Set the flag to use the settings
useSet = True
return {'FINISHED'}
-class PresetMenu(bpy.types.Menu):
+
+class PresetMenu(Menu):
"""Create the preset menu by finding all preset files
in the preset directory"""
bl_idname = "sapling.presetmenu"
@@ -234,7 +246,8 @@ class PresetMenu(bpy.types.Menu):
for p in presets:
layout.operator("sapling.importdata", text=p[:-3]).filename = p
-class AddTree(bpy.types.Operator):
+
+class AddTree(Operator):
bl_idname = "curve.tree_add"
bl_label = "Sapling: Add Tree"
bl_options = {'REGISTER', 'UNDO'}
@@ -242,16 +255,13 @@ class AddTree(bpy.types.Operator):
def objectList(self, context):
objects = []
bObjects = bpy.data.objects
-# try:
-# bObjects = bpy.data.objects
-# except AttributeError:
-# pass
-# else:
+
for obj in bObjects:
if (obj.type in ['MESH', 'CURVE', 'SURFACE']) and (obj.name not in ['tree', 'leaves']):
objects.append((obj.name, obj.name, ""))
- return objects
+ return (objects if objects else
+ [('NONE', "No objects", "No appropriate objects in the Scene")])
def update_tree(self, context):
self.do_update = True
@@ -265,419 +275,606 @@ class AddTree(bpy.types.Operator):
def no_update_tree(self, context):
self.do_update = False
- do_update = BoolProperty(name='Do Update',
- default=True, options={'HIDDEN'})
-
- chooseSet = EnumProperty(name='Settings',
+ do_update = BoolProperty(
+ name='Do Update',
+ default=True, options={'HIDDEN'}
+ )
+ chooseSet = EnumProperty(
+ name='Settings',
description='Choose the settings to modify',
items=settings,
- default='0', update=no_update_tree)
- bevel = BoolProperty(name='Bevel',
+ default='0', update=no_update_tree
+ )
+ bevel = BoolProperty(
+ name='Bevel',
description='Whether the curve is beveled',
- default=False, update=update_tree)
- prune = BoolProperty(name='Prune',
+ default=False, update=update_tree
+ )
+ prune = BoolProperty(
+ name='Prune',
description='Whether the tree is pruned',
- default=False, update=update_tree)
- showLeaves = BoolProperty(name='Show Leaves',
+ default=False, update=update_tree
+ )
+ showLeaves = BoolProperty(
+ name='Show Leaves',
description='Whether the leaves are shown',
- default=False, update=update_tree)
- useArm = BoolProperty(name='Use Armature',
+ default=False, update=update_tree
+ )
+ useArm = BoolProperty(
+ name='Use Armature',
description='Whether the armature is generated',
- default=False, update=update_tree)
- seed = IntProperty(name='Random Seed',
+ default=False, update=update_tree
+ )
+ seed = IntProperty(
+ name='Random Seed',
description='The seed of the random number generator',
- default=0, update=update_tree)
- handleType = IntProperty(name='Handle Type',
+ default=0, update=update_tree
+ )
+ handleType = IntProperty(
+ name='Handle Type',
description='The type of curve handles',
min=0,
max=1,
- default=0, update=update_tree)
- levels = IntProperty(name='Levels',
+ default=0, update=update_tree
+ )
+ levels = IntProperty(
+ name='Levels',
description='Number of recursive branches (Levels)',
min=1,
max=6,
soft_max=4,
- default=3, update=update_tree)
- length = FloatVectorProperty(name='Length',
+ default=3, update=update_tree
+ )
+ length = FloatVectorProperty(
+ name='Length',
description='The relative lengths of each branch level (nLength)',
min=0.000001,
default=[1, 0.3, 0.6, 0.45],
- size=4, update=update_tree)
- lengthV = FloatVectorProperty(name='Length Variation',
+ size=4, update=update_tree
+ )
+ lengthV = FloatVectorProperty(
+ name='Length Variation',
description='The relative length variations of each level (nLengthV)',
min=0.0,
max=1.0,
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- taperCrown = FloatProperty(name='Taper Crown',
+ size=4, update=update_tree
+ )
+ taperCrown = FloatProperty(
+ name='Taper Crown',
description='Shorten trunk splits toward outside of tree',
min=0.0,
soft_max=1.0,
- default=0, update=update_tree)
- branches = IntVectorProperty(name='Branches',
+ default=0, update=update_tree
+ )
+ branches = IntVectorProperty(
+ name='Branches',
description='The number of branches grown at each level (nBranches)',
min=0,
default=[50, 30, 10, 10],
- size=4, update=update_tree)
- curveRes = IntVectorProperty(name='Curve Resolution',
+ size=4, update=update_tree
+ )
+ curveRes = IntVectorProperty(
+ name='Curve Resolution',
description='The number of segments on each branch (nCurveRes)',
min=1,
default=[3, 5, 3, 1],
- size=4, update=update_tree)
- curve = FloatVectorProperty(name='Curvature',
+ size=4, update=update_tree
+ )
+ curve = FloatVectorProperty(
+ name='Curvature',
description='The angle of the end of the branch (nCurve)',
default=[0, -40, -40, 0],
- size=4, update=update_tree)
- curveV = FloatVectorProperty(name='Curvature Variation',
+ size=4, update=update_tree
+ )
+ curveV = FloatVectorProperty(
+ name='Curvature Variation',
description='Variation of the curvature (nCurveV)',
default=[20, 50, 75, 0],
- size=4, update=update_tree)
- curveBack = FloatVectorProperty(name='Back Curvature',
+ size=4, update=update_tree
+ )
+ curveBack = FloatVectorProperty(
+ name='Back Curvature',
description='Curvature for the second half of a branch (nCurveBack)',
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- baseSplits = IntProperty(name='Base Splits',
+ size=4, update=update_tree
+ )
+ baseSplits = IntProperty(
+ name='Base Splits',
description='Number of trunk splits at its base (nBaseSplits)',
min=0,
- default=0, update=update_tree)
- segSplits = FloatVectorProperty(name='Segment Splits',
+ default=0, update=update_tree
+ )
+ segSplits = FloatVectorProperty(
+ name='Segment Splits',
description='Number of splits per segment (nSegSplits)',
min=0,
soft_max=3,
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- splitByLen = BoolProperty(name='Split relative to length',
+ size=4, update=update_tree
+ )
+ splitByLen = BoolProperty(
+ name='Split relative to length',
description='Split proportional to branch length',
- default=False, update=update_tree)
- rMode = EnumProperty(name="", #"Branching Mode"
+ default=False, update=update_tree
+ )
+ rMode = EnumProperty(
+ name="", # "Branching Mode"
description='Branching and Rotation Mode',
items=branchmodes,
- default="rotate", update=update_tree)
- splitAngle = FloatVectorProperty(name='Split Angle',
+ default="rotate", update=update_tree
+ )
+ splitAngle = FloatVectorProperty(
+ name='Split Angle',
description='Angle of branch splitting (nSplitAngle)',
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- splitAngleV = FloatVectorProperty(name='Split Angle Variation',
+ size=4, update=update_tree
+ )
+ splitAngleV = FloatVectorProperty(
+ name='Split Angle Variation',
description='Variation in the split angle (nSplitAngleV)',
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- scale = FloatProperty(name='Scale',
+ size=4, update=update_tree
+ )
+ scale = FloatProperty(
+ name='Scale',
description='The tree scale (Scale)',
min=0.0,
default=13.0, update=update_tree)
scaleV = FloatProperty(name='Scale Variation',
description='The variation in the tree scale (ScaleV)',
- default=3.0, update=update_tree)
- attractUp = FloatVectorProperty(name='Vertical Attraction',
+ default=3.0, update=update_tree
+ )
+ attractUp = FloatVectorProperty(
+ name='Vertical Attraction',
description='Branch upward attraction',
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- attractOut = FloatVectorProperty(name='Outward Attraction',
+ size=4, update=update_tree
+ )
+ attractOut = FloatVectorProperty(
+ name='Outward Attraction',
description='Branch outward attraction',
default=[0, 0, 0, 0],
min=0.0,
max=1.0,
- size=4, update=update_tree)
- shape = EnumProperty(name='Shape',
+ size=4, update=update_tree
+ )
+ shape = EnumProperty(
+ name='Shape',
description='The overall shape of the tree (Shape)',
items=shapeList3,
- default='7', update=update_tree)
- shapeS = EnumProperty(name='Secondary Branches Shape',
+ default='7', update=update_tree
+ )
+ shapeS = EnumProperty(
+ name='Secondary Branches Shape',
description='The shape of secondary splits',
items=shapeList4,
- default='4', update=update_tree)
- customShape = FloatVectorProperty(name='Custom Shape',
+ default='4', update=update_tree
+ )
+ customShape = FloatVectorProperty(
+ name='Custom Shape',
description='custom shape branch length at (Base, Middle, Middle Position, Top)',
size=4,
min=.01,
max=1,
- default=[.5, 1.0, .3, .5], update=update_tree)
- branchDist = FloatProperty(name='Branch Distribution',
+ default=[.5, 1.0, .3, .5], update=update_tree
+ )
+ branchDist = FloatProperty(
+ name='Branch Distribution',
description='Adjust branch spacing to put more branches at the top or bottom of the tree',
min=0.1,
soft_max=10,
- default=1.0, update=update_tree)
- nrings = IntProperty(name='Branch Rings',
+ default=1.0, update=update_tree
+ )
+ nrings = IntProperty(
+ name='Branch Rings',
description='grow branches in rings',
min=0,
- default=0, update=update_tree)
- baseSize = FloatProperty(name='Trunk Height',
+ default=0, update=update_tree
+ )
+ baseSize = FloatProperty(
+ name='Trunk Height',
description='Fraction of tree height with no branches (Base Size)',
min=0.0,
max=1.0,
- default=0.4, update=update_tree)
- baseSize_s = FloatProperty(name='Secondary Base Size',
+ default=0.4, update=update_tree
+ )
+ baseSize_s = FloatProperty(
+ name='Secondary Base Size',
description='Factor to decrease base size for each level',
min=0.0,
max=1.0,
- default=0.25, update=update_tree)
- splitHeight = FloatProperty(name='Split Height',
+ default=0.25, update=update_tree
+ )
+ splitHeight = FloatProperty(
+ name='Split Height',
description='Fraction of tree height with no splits',
min=0.0,
max=1.0,
- default=0.2, update=update_tree)
- splitBias = FloatProperty(name='splitBias',
+ default=0.2, update=update_tree
+ )
+ splitBias = FloatProperty(
+ name='splitBias',
description='Put more splits at the top or bottom of the tree',
soft_min=-2.0,
soft_max=2.0,
- default=0.0, update=update_tree)
- ratio = FloatProperty(name='Ratio',
+ default=0.0, update=update_tree
+ )
+ ratio = FloatProperty(
+ name='Ratio',
description='Base radius size (Ratio)',
min=0.0,
- default=0.015, update=update_tree)
- minRadius = FloatProperty(name='Minimum Radius',
+ default=0.015, update=update_tree
+ )
+ minRadius = FloatProperty(
+ name='Minimum Radius',
description='Minimum branch Radius',
min=0.0,
- default=0.0, update=update_tree)
- closeTip = BoolProperty(name='Close Tip',
+ default=0.0, update=update_tree
+ )
+ closeTip = BoolProperty(
+ name='Close Tip',
description='Set radius at branch tips to zero',
- default=False, update=update_tree)
- rootFlare = FloatProperty(name='Root Flare',
+ default=False, update=update_tree
+ )
+ rootFlare = FloatProperty(
+ name='Root Flare',
description='Root radius factor',
min=1.0,
- default=1.0, update=update_tree)
- autoTaper = BoolProperty(name='Auto Taper',
+ default=1.0, update=update_tree
+ )
+ autoTaper = BoolProperty(
+ name='Auto Taper',
description='Calculate taper automaticly based on branch lengths',
- default=True, update=update_tree)
- taper = FloatVectorProperty(name='Taper',
+ default=True, update=update_tree
+ )
+ taper = FloatVectorProperty(
+ name='Taper',
description='The fraction of tapering on each branch (nTaper)',
min=0.0,
max=1.0,
default=[1, 1, 1, 1],
- size=4, update=update_tree)
- radiusTweak = FloatVectorProperty(name='Tweak Radius',
+ size=4, update=update_tree
+ )
+ radiusTweak = FloatVectorProperty(
+ name='Tweak Radius',
description='multiply radius by this factor',
min=0.0,
max=1.0,
default=[1, 1, 1, 1],
- size=4, update=update_tree)
- ratioPower = FloatProperty(name='Branch Radius Ratio',
+ size=4, update=update_tree
+ )
+ ratioPower = FloatProperty(
+ name='Branch Radius Ratio',
description=('Power which defines the radius of a branch compared to '
'the radius of the branch it grew from (RatioPower)'),
min=0.0,
- default=1.2, update=update_tree)
- downAngle = FloatVectorProperty(name='Down Angle',
+ default=1.2, update=update_tree
+ )
+ downAngle = FloatVectorProperty(
+ name='Down Angle',
description=('The angle between a new branch and the one it grew '
'from (nDownAngle)'),
default=[90, 60, 45, 45],
- size=4, update=update_tree)
- downAngleV = FloatVectorProperty(name='Down Angle Variation',
- description='Angle to decrease Down Angle by towards end of parent branch (negative values add random variation)',
+ size=4, update=update_tree
+ )
+ downAngleV = FloatVectorProperty(
+ name='Down Angle Variation',
+ description="Angle to decrease Down Angle by towards end of parent branch "
+ "(negative values add random variation)",
default=[0, -50, 10, 10],
- size=4, update=update_tree)
- useOldDownAngle = BoolProperty(name='Use old down angle variation',
- default=False, update=update_tree)
- useParentAngle = BoolProperty(name = 'Use parent angle',
- description = '(first level) Rotate branch to match parent branch',
- default=True, update=update_tree)
- rotate = FloatVectorProperty(name='Rotate Angle',
- description='The angle of a new branch around the one it grew from (negative values rotate opposite from the previous)',
+ size=4, update=update_tree
+ )
+ useOldDownAngle = BoolProperty(
+ name='Use old down angle variation',
+ default=False, update=update_tree
+ )
+ useParentAngle = BoolProperty(
+ name='Use parent angle',
+ description='(first level) Rotate branch to match parent branch',
+ default=True, update=update_tree
+ )
+ rotate = FloatVectorProperty(
+ name='Rotate Angle',
+ description="The angle of a new branch around the one it grew from "
+ "(negative values rotate opposite from the previous)",
default=[137.5, 137.5, 137.5, 137.5],
- size=4, update=update_tree)
- rotateV = FloatVectorProperty(name='Rotate Angle Variation',
+ size=4, update=update_tree
+ )
+ rotateV = FloatVectorProperty(
+ name='Rotate Angle Variation',
description='Variation in the rotate angle (nRotateV)',
default=[0, 0, 0, 0],
- size=4, update=update_tree)
- scale0 = FloatProperty(name='Radius Scale',
+ size=4, update=update_tree
+ )
+ scale0 = FloatProperty(
+ name='Radius Scale',
description='The scale of the trunk radius (0Scale)',
min=0.0,
- default=1.0, update=update_tree)
- scaleV0 = FloatProperty(name='Radius Scale Variation',
+ default=1.0, update=update_tree
+ )
+ scaleV0 = FloatProperty(
+ name='Radius Scale Variation',
description='Variation in the radius scale (0ScaleV)',
min=0.0,
max=1.0,
- default=0.2, update=update_tree)
- pruneWidth = FloatProperty(name='Prune Width',
+ default=0.2, update=update_tree
+ )
+ pruneWidth = FloatProperty(
+ name='Prune Width',
description='The width of the envelope (PruneWidth)',
min=0.0,
- default=0.4, update=update_tree)
- pruneBase = FloatProperty(name='Prune Base Height',
+ default=0.4, update=update_tree
+ )
+ pruneBase = FloatProperty(
+ name='Prune Base Height',
description='The height of the base of the envelope, bound by trunk height',
min=0.0,
max=1.0,
- default=0.3, update=update_tree)
- pruneWidthPeak = FloatProperty(name='Prune Width Peak',
- description=('Fraction of envelope height where the maximum width '
- 'occurs (PruneWidthPeak)'),
+ default=0.3, update=update_tree
+ )
+ pruneWidthPeak = FloatProperty(
+ name='Prune Width Peak',
+ description=("Fraction of envelope height where the maximum width "
+ "occurs (PruneWidthPeak)"),
min=0.0,
- default=0.6, update=update_tree)
- prunePowerHigh = FloatProperty(name='Prune Power High',
+ default=0.6, update=update_tree
+ )
+ prunePowerHigh = FloatProperty(
+ name='Prune Power High',
description=('Power which determines the shape of the upper portion '
'of the envelope (PrunePowerHigh)'),
- default=0.5, update=update_tree)
- prunePowerLow = FloatProperty(name='Prune Power Low',
+ default=0.5, update=update_tree
+ )
+ prunePowerLow = FloatProperty(
+ name='Prune Power Low',
description=('Power which determines the shape of the lower portion '
'of the envelope (PrunePowerLow)'),
- default=0.001, update=update_tree)
- pruneRatio = FloatProperty(name='Prune Ratio',
+ default=0.001, update=update_tree
+ )
+ pruneRatio = FloatProperty(
+ name='Prune Ratio',
description='Proportion of pruned length (PruneRatio)',
min=0.0,
max=1.0,
- default=1.0, update=update_tree)
- leaves = IntProperty(name='Leaves',
- description='Maximum number of leaves per branch (negative values grow leaves from branch tip (palmate compound leaves))',
- default=25, update=update_tree)
-
- leafDownAngle = FloatProperty(name='Leaf Down Angle',
+ default=1.0, update=update_tree
+ )
+ leaves = IntProperty(
+ name='Leaves',
+ description="Maximum number of leaves per branch (negative values grow "
+ "leaves from branch tip (palmate compound leaves))",
+ default=25, update=update_tree
+ )
+ leafDownAngle = FloatProperty(
+ name='Leaf Down Angle',
description='The angle between a new leaf and the branch it grew from',
- default=45, update=update_leaves)
- leafDownAngleV = FloatProperty(name='Leaf Down Angle Variation',
- description='Angle to decrease Down Angle by towards end of parent branch (negative values add random variation)',
- default=10, update=update_tree)
- leafRotate = FloatProperty(name='Leaf Rotate Angle',
- description='The angle of a new leaf around the one it grew from (negative values rotate opposite from previous)',
- default=137.5, update=update_tree)
- leafRotateV = FloatProperty(name='Leaf Rotate Angle Variation',
+ default=45, update=update_leaves
+ )
+ leafDownAngleV = FloatProperty(
+ name='Leaf Down Angle Variation',
+ description="Angle to decrease Down Angle by towards end of parent branch "
+ "(negative values add random variation)",
+ default=10, update=update_tree
+ )
+ leafRotate = FloatProperty(
+ name='Leaf Rotate Angle',
+ description="The angle of a new leaf around the one it grew from "
+ "(negative values rotate opposite from previous)",
+ default=137.5, update=update_tree
+ )
+ leafRotateV = FloatProperty(
+ name='Leaf Rotate Angle Variation',
description='Variation in the rotate angle',
- default=0.0, update=update_leaves)
-
- leafScale = FloatProperty(name='Leaf Scale',
+ default=0.0, update=update_leaves
+ )
+ leafScale = FloatProperty(
+ name='Leaf Scale',
description='The scaling applied to the whole leaf (LeafScale)',
min=0.0,
- default=0.17, update=update_leaves)
- leafScaleX = FloatProperty(name='Leaf Scale X',
+ default=0.17, update=update_leaves
+ )
+ leafScaleX = FloatProperty(
+ name='Leaf Scale X',
description=('The scaling applied to the x direction of the leaf '
'(LeafScaleX)'),
min=0.0,
- default=1.0, update=update_leaves)
- leafScaleT = FloatProperty(name='Leaf Scale Taper',
+ default=1.0, update=update_leaves
+ )
+ leafScaleT = FloatProperty(
+ name='Leaf Scale Taper',
description='scale leaves toward the tip or base of the patent branch',
- min = -1.0,
- max = 1.0,
- default=0.0, update=update_leaves)
- leafScaleV = FloatProperty(name='Leaf Scale Variation',
+ min=-1.0,
+ max=1.0,
+ default=0.0, update=update_leaves
+ )
+ leafScaleV = FloatProperty(
+ name='Leaf Scale Variation',
description='randomize leaf scale',
- min = 0.0,
- max = 1.0,
- default=0.0, update=update_leaves)
- leafShape = EnumProperty(name='Leaf Shape',
+ min=0.0,
+ max=1.0,
+ default=0.0, update=update_leaves
+ )
+ leafShape = EnumProperty(
+ name='Leaf Shape',
description='The shape of the leaves',
- items=(('hex', 'Hexagonal', '0'), ('rect', 'Rectangular', '1'), ('dFace', 'DupliFaces', '2'), ('dVert', 'DupliVerts', '3')),
- default='hex', update=update_leaves)
- leafDupliObj = EnumProperty(name='Leaf Object',
+ items=(('hex', 'Hexagonal', '0'), ('rect', 'Rectangular', '1'),
+ ('dFace', 'DupliFaces', '2'), ('dVert', 'DupliVerts', '3')),
+ default='hex', update=update_leaves
+ )
+ leafDupliObj = EnumProperty(
+ name='Leaf Object',
description='Object to use for leaf instancing if Leaf Shape is DupliFaces or DupliVerts',
items=objectList,
- update=update_leaves)
-
-# bend = FloatProperty(name='Leaf Bend',
-# description='The proportion of bending applied to the leaf (Bend)',
-# min=0.0,
-# max=1.0,
-# default=0.0, update=update_leaves)
-
- leafangle = FloatProperty(name='Leaf Angle',
+ update=update_leaves
+ )
+ """
+ bend = FloatProperty(
+ name='Leaf Bend',
+ description='The proportion of bending applied to the leaf (Bend)',
+ min=0.0,
+ max=1.0,
+ default=0.0, update=update_leaves
+ )
+ """
+ leafangle = FloatProperty(
+ name='Leaf Angle',
description='Leaf vertical attraction',
- default=0.0, update=update_leaves)
- horzLeaves = BoolProperty(name='Horizontal leaves',
+ default=0.0, update=update_leaves
+ )
+ horzLeaves = BoolProperty(
+ name='Horizontal leaves',
description='Leaves face upwards',
- default=True, update=update_leaves)
- leafDist = EnumProperty(name='Leaf Distribution',
+ default=True, update=update_leaves
+ )
+ leafDist = EnumProperty(
+ name='Leaf Distribution',
description='The way leaves are distributed on branches',
items=shapeList4,
- default='6', update=update_tree)
- bevelRes = IntProperty(name='Bevel Resolution',
+ default='6', update=update_tree
+ )
+ bevelRes = IntProperty(
+ name='Bevel Resolution',
description='The bevel resolution of the curves',
min=0,
max=32,
- default=0, update=update_tree)
- resU = IntProperty(name='Curve Resolution',
+ default=0, update=update_tree
+ )
+ resU = IntProperty(
+ name='Curve Resolution',
description='The resolution along the curves',
min=1,
- default=4, update=update_tree)
- handleType = EnumProperty(name='Handle Type',
+ default=4, update=update_tree
+ )
+ handleType = EnumProperty(
+ name='Handle Type',
description='The type of handles used in the spline',
items=handleList,
- default='0', update=update_tree)
-
- armAnim = BoolProperty(name='Armature Animation',
+ default='0', update=update_tree
+ )
+ armAnim = BoolProperty(
+ name='Armature Animation',
description='Whether animation is added to the armature',
- default=False, update=update_tree)
- previewArm = BoolProperty(name='Fast Preview',
+ default=False, update=update_tree
+ )
+ previewArm = BoolProperty(
+ name='Fast Preview',
description='Disable armature modifier, hide tree, and set bone display to wire, for fast playback',
- ##Disable skin modifier and hide tree and armature, for fast playback
- default=False, update=update_tree)
- leafAnim = BoolProperty(name='Leaf Animation',
+ # Disable skin modifier and hide tree and armature, for fast playback
+ default=False, update=update_tree
+ )
+ leafAnim = BoolProperty(
+ name='Leaf Animation',
description='Whether animation is added to the leaves',
- default=False, update=update_tree)
- frameRate = FloatProperty(name='Animation Speed',
+ default=False, update=update_tree
+ )
+ frameRate = FloatProperty(
+ name='Animation Speed',
description=('Adjust speed of animation, relative to scene frame rate'),
min=0.001,
- default=1, update=update_tree)
- loopFrames = IntProperty(name='Loop Frames',
+ default=1, update=update_tree
+ )
+ loopFrames = IntProperty(
+ name='Loop Frames',
description='Number of frames to make the animation loop for, zero is disabled',
min=0,
- default=0, update=update_tree)
-
-# windSpeed = FloatProperty(name='Wind Speed',
-# description='The wind speed to apply to the armature',
-# default=2.0, update=update_tree)
-# windGust = FloatProperty(name='Wind Gust',
-# description='The greatest increase over Wind Speed',
-# default=0.0, update=update_tree)
-
- wind= FloatProperty(name='Overall Wind Strength',
+ default=0, update=update_tree
+ )
+ """
+ windSpeed = FloatProperty(
+ name='Wind Speed',
+ description='The wind speed to apply to the armature',
+ default=2.0, update=update_tree
+ )
+ windGust = FloatProperty(
+ name='Wind Gust',
+ description='The greatest increase over Wind Speed',
+ default=0.0, update=update_tree
+ )
+ """
+ wind = FloatProperty(
+ name='Overall Wind Strength',
description='The intensity of the wind to apply to the armature',
- default=1.0, update=update_tree)
-
- gust = FloatProperty(name='Wind Gust Strength',
+ default=1.0, update=update_tree
+ )
+ gust = FloatProperty(
+ name='Wind Gust Strength',
description='The amount of directional movement, (from the positive Y direction)',
- default=1.0, update=update_tree)
-
- gustF = FloatProperty(name='Wind Gust Fequency',
+ default=1.0, update=update_tree
+ )
+ gustF = FloatProperty(
+ name='Wind Gust Fequency',
description='The Fequency of directional movement',
- default=0.075, update=update_tree)
-
- af1 = FloatProperty(name='Amplitude',
+ default=0.075, update=update_tree
+ )
+ af1 = FloatProperty(
+ name='Amplitude',
description='Multiplier for noise amplitude',
- default=1.0, update=update_tree)
- af2 = FloatProperty(name='Frequency',
+ default=1.0, update=update_tree
+ )
+ af2 = FloatProperty(
+ name='Frequency',
description='Multiplier for noise fequency',
- default=1.0, update=update_tree)
- af3 = FloatProperty(name='Randomness',
+ default=1.0, update=update_tree
+ )
+ af3 = FloatProperty(
+ name='Randomness',
description='Random offset in noise',
- default=4.0, update=update_tree)
-
- makeMesh = BoolProperty(name='Make Mesh',
+ default=4.0, update=update_tree
+ )
+ makeMesh = BoolProperty(
+ name='Make Mesh',
description='Convert curves to mesh, uses skin modifier, enables armature simplification',
- default=False, update=update_tree)
- armLevels = IntProperty(name='Armature Levels',
+ default=False, update=update_tree
+ )
+ armLevels = IntProperty(
+ name='Armature Levels',
description='Number of branching levels to make bones for, 0 is all levels',
min=0,
- default=2, update=update_tree)
- boneStep = IntVectorProperty(name='Bone Length',
+ default=2, update=update_tree
+ )
+ boneStep = IntVectorProperty(
+ name='Bone Length',
description='Number of stem segments per bone',
min=1,
default=[1, 1, 1, 1],
- size=4, update=update_tree)
-
- presetName = StringProperty(name='Preset Name',
+ size=4, update=update_tree
+ )
+ presetName = StringProperty(
+ name='Preset Name',
description='The name of the preset to be saved',
default='',
- subtype='FILE_NAME', update=no_update_tree)
- limitImport = BoolProperty(name='Limit Import',
+ subtype='FILE_NAME', update=no_update_tree
+ )
+ limitImport = BoolProperty(
+ name='Limit Import',
description='Limited imported tree to 2 levels & no leaves for speed',
- default=True, update=no_update_tree)
- overwrite = BoolProperty(name='Overwrite',
+ default=True, update=no_update_tree
+ )
+ overwrite = BoolProperty(
+ name='Overwrite',
description='When checked, overwrite existing preset files when saving',
- default=False, update=no_update_tree)
-
-# startCurv = FloatProperty(name='Trunk Starting Angle',
-# description=('The angle between vertical and the starting direction '
-# 'of the trunk'),
-# min=0.0,
-# max=360,
-# default=0.0, update=update_tree)
+ default=False, update=no_update_tree
+ )
+ """
+ startCurv = FloatProperty(
+ name='Trunk Starting Angle',
+ description=('The angle between vertical and the starting direction'
+ 'of the trunk'),
+ min=0.0,
+ max=360,
+ default=0.0, update=update_tree
+ )
+ """
@classmethod
def poll(cls, context):
return context.mode == 'OBJECT'
def draw(self, context):
-
layout = self.layout
# Branch specs
- #layout.label('Tree Definition')
+ # layout.label('Tree Definition')
layout.prop(self, 'chooseSet')
@@ -711,7 +908,9 @@ class AddTree(bpy.types.Operator):
# Unfortunately as_keyword doesn't work with vector properties,
# so we need something custom. This is it
data = []
- for a, b in (self.as_keywords(ignore=("chooseSet", "presetName", "limitImport", "do_update", "overwrite", "leafDupliObj"))).items():
+ for a, b in (self.as_keywords(
+ ignore=("chooseSet", "presetName", "limitImport",
+ "do_update", "overwrite", "leafDupliObj"))).items():
# If the property is a vector property then add the slice to the list
try:
len(b)
@@ -856,8 +1055,8 @@ class AddTree(bpy.types.Operator):
box.prop(self, 'horzLeaves')
box.prop(self, 'leafangle')
- #box.label(" ")
- #box.prop(self, 'bend')
+ # box.label(" ")
+ # box.prop(self, 'bend')
elif self.chooseSet == '6':
box = layout.box()
@@ -878,9 +1077,9 @@ class AddTree(bpy.types.Operator):
box.prop(self, 'frameRate')
box.prop(self, 'loopFrames')
- #row = box.row()
- #row.prop(self, 'windSpeed')
- #row.prop(self, 'windGust')
+ # row = box.row()
+ # row.prop(self, 'windSpeed')
+ # row.prop(self, 'windGust')
box.label('Wind Settings:')
box.prop(self, 'wind')
@@ -897,7 +1096,7 @@ class AddTree(bpy.types.Operator):
# Ensure the use of the global variables
global settings, useSet
start_time = time.time()
- #bpy.ops.ImportData.filename = "quaking_aspen"
+ # bpy.ops.ImportData.filename = "quaking_aspen"
# If we need to set the properties from a preset then do it here
if useSet:
for a, b in settings.items():
@@ -908,29 +1107,32 @@ class AddTree(bpy.types.Operator):
useSet = False
if not self.do_update:
return {'PASS_THROUGH'}
- addTree(self)
- #cProfile.runctx("addTree(self)", globals(), locals())
- print("Tree creation in %0.1fs" %(time.time()-start_time))
+ utils.addTree(self)
+ # cProfile.runctx("addTree(self)", globals(), locals())
+ print("Tree creation in %0.1fs" % (time.time() - start_time))
+
return {'FINISHED'}
def invoke(self, context, event):
-# global settings, useSet
-# useSet = True
- bpy.ops.sapling.importdata(filename = "quaking_aspen.py")
+ bpy.ops.sapling.importdata(filename="quaking_aspen.py")
return self.execute(context)
+
def menu_func(self, context):
self.layout.operator(AddTree.bl_idname, text="Sapling Tree Gen", icon='CURVE_DATA')
+
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_curve_add.append(menu_func)
+
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_curve_add.remove(menu_func)
+
if __name__ == "__main__":
register()
diff --git a/add_curve_sapling/utils.py b/add_curve_sapling/utils.py
index 55c0f14f..e33df130 100644
--- a/add_curve_sapling/utils.py
+++ b/add_curve_sapling/utils.py
@@ -16,17 +16,19 @@
#
# ##### END GPL LICENSE BLOCK #####
-print("version 3 imported")
import bpy
import time
import copy
-from mathutils import *
+from mathutils import (
+ Euler,
+ Matrix,
+ Vector,
+ )
from math import pi, sin, degrees, radians, atan2, copysign, cos, acos
-from math import floor, ceil
+from math import floor
from random import random, uniform, seed, choice, getstate, setstate, randint
-from bpy.props import *
from collections import deque, OrderedDict
tau = 2 * pi
@@ -37,9 +39,11 @@ zAxis = Vector((0, 0, 1))
yAxis = Vector((0, 1, 0))
xAxis = Vector((1, 0, 0))
+
# This class will contain a part of the tree which needs to be extended and the required tree parameters
class stemSpline:
- def __init__(self, spline, curvature, curvatureV, attractUp, segments, maxSegs, segLength, childStems, stemRadStart, stemRadEnd, splineNum, ofst, pquat):
+ def __init__(self, spline, curvature, curvatureV, attractUp, segments, maxSegs,
+ segLength, childStems, stemRadStart, stemRadEnd, splineNum, ofst, pquat):
self.spline = spline
self.p = spline.bezier_points[-1]
self.curv = curvature
@@ -60,19 +64,24 @@ class stemSpline:
# This method determines the quaternion of the end of the spline
def quat(self):
if len(self.spline.bezier_points) == 1:
- return ((self.spline.bezier_points[-1].handle_right - self.spline.bezier_points[-1].co).normalized()).to_track_quat('Z', 'Y')
+ return ((self.spline.bezier_points[-1].handle_right -
+ self.spline.bezier_points[-1].co).normalized()).to_track_quat('Z', 'Y')
else:
- return ((self.spline.bezier_points[-1].co - self.spline.bezier_points[-2].co).normalized()).to_track_quat('Z', 'Y')
+ return ((self.spline.bezier_points[-1].co -
+ self.spline.bezier_points[-2].co).normalized()).to_track_quat('Z', 'Y')
+
# Determine the declination
def dec(self):
tempVec = zAxis.copy()
tempVec.rotate(self.quat())
return zAxis.angle(tempVec)
+
# Update the end of the spline and increment the segment count
def updateEnd(self):
self.p = self.spline.bezier_points[-1]
self.seg += 1
+
# This class contains the data for a point where a new branch will sprout
class childPoint:
def __init__(self, coords, quat, radiusPar, offset, sOfst, lengthPar, parBone):
@@ -88,39 +97,39 @@ class childPoint:
# This function calculates the shape ratio as defined in the paper
def shapeRatio(shape, ratio, pruneWidthPeak=0.0, prunePowerHigh=0.0, prunePowerLow=0.0, custom=None):
if shape == 0:
- return 0.05 + 0.95*ratio #0.2 + 0.8*ratio
+ return 0.05 + 0.95 * ratio # 0.2 + 0.8 * ratio
elif shape == 1:
- return 0.2 + 0.8*sin(pi*ratio)
+ return 0.2 + 0.8 * sin(pi * ratio)
elif shape == 2:
- return 0.2 + 0.8*sin(0.5*pi*ratio)
+ return 0.2 + 0.8 * sin(0.5 * pi * ratio)
elif shape == 3:
return 1.0
elif shape == 4:
- return 0.5 + 0.5*ratio
+ return 0.5 + 0.5 * ratio
elif shape == 5:
if ratio <= 0.7:
- return 0.05 + 0.95 * ratio/0.7
+ return 0.05 + 0.95 * ratio / 0.7
else:
- return 0.05 + 0.95 * (1.0 - ratio)/0.3
+ return 0.05 + 0.95 * (1.0 - ratio) / 0.3
elif shape == 6:
- return 1.0 - 0.8*ratio
+ return 1.0 - 0.8 * ratio
elif shape == 7:
if ratio <= 0.7:
- return 0.5 + 0.5*ratio/0.7
+ return 0.5 + 0.5 * ratio / 0.7
else:
- return 0.5 + 0.5*(1.0 - ratio)/0.3
+ return 0.5 + 0.5 * (1.0 - ratio) / 0.3
elif shape == 8:
r = 1 - ratio
if r == 1:
v = custom[3]
elif r >= custom[2]:
pos = (r - custom[2]) / (1 - custom[2])
- #if (custom[0] >= custom[1] <= custom[3]) or (custom[0] <= custom[1] >= custom[3]):
+ # if (custom[0] >= custom[1] <= custom[3]) or (custom[0] <= custom[1] >= custom[3]):
pos = pos * pos
v = (pos * (custom[3] - custom[1])) + custom[1]
else:
pos = r / custom[2]
- #if (custom[0] >= custom[1] <= custom[3]) or (custom[0] <= custom[1] >= custom[3]):
+ # if (custom[0] >= custom[1] <= custom[3]) or (custom[0] <= custom[1] >= custom[3]):
pos = 1 - (1 - pos) * (1 - pos)
v = (pos * (custom[1] - custom[0])) + custom[0]
@@ -128,15 +137,16 @@ def shapeRatio(shape, ratio, pruneWidthPeak=0.0, prunePowerHigh=0.0, prunePowerL
elif shape == 9:
if (ratio < (1 - pruneWidthPeak)) and (ratio > 0.0):
- return ((ratio/(1 - pruneWidthPeak))**prunePowerHigh)
+ return ((ratio / (1 - pruneWidthPeak))**prunePowerHigh)
elif (ratio >= (1 - pruneWidthPeak)) and (ratio < 1.0):
- return (((1 - ratio)/pruneWidthPeak)**prunePowerLow)
+ return (((1 - ratio) / pruneWidthPeak)**prunePowerLow)
else:
return 0.0
elif shape == 10:
return 0.5 + 0.5 * (1 - ratio)
+
# This function determines the actual number of splits at a given point using the global error
def splits(n):
global splitError
@@ -144,6 +154,7 @@ def splits(n):
splitError -= (nEff - n)
return int(nEff)
+
def splits2(n):
r = random()
if r < n:
@@ -151,6 +162,7 @@ def splits2(n):
else:
return 0
+
def splits3(n):
ni = int(n)
nf = n - int(n)
@@ -160,6 +172,7 @@ def splits3(n):
else:
return ni + 0
+
# Determine the declination from a given quaternion
def declination(quat):
tempVec = zAxis.copy()
@@ -167,6 +180,7 @@ def declination(quat):
tempVec.normalize()
return degrees(acos(tempVec.z))
+
# Determines the angle of upward rotation of a segment due to attractUp
def curveUp(attractUp, quat, curveRes):
tempVec = yAxis.copy()
@@ -174,32 +188,40 @@ def curveUp(attractUp, quat, curveRes):
tempVec.normalize()
dec = radians(declination(quat))
- curveUpAng = attractUp*dec*abs(tempVec.z)/curveRes
+ curveUpAng = attractUp * dec * abs(tempVec.z) / curveRes
if (-dec + curveUpAng) < -pi:
curveUpAng = -pi + dec
if (dec - curveUpAng) < 0:
curveUpAng = dec
return curveUpAng
+
# Evaluate a bezier curve for the parameter 0<=t<=1 along its length
def evalBez(p1, h1, h2, p2, t):
- return ((1-t)**3)*p1 + (3*t*(1-t)**2)*h1 + (3*(t**2)*(1-t))*h2 + (t**3)*p2
+ return ((1 - t)**3) * p1 + (3 * t * (1 - t)**2) * h1 + (3 * (t**2) * (1 - t)) * h2 + (t**3) * p2
+
# Evaluate the unit tangent on a bezier curve for t
def evalBezTan(p1, h1, h2, p2, t):
- return ((-3*(1-t)**2)*p1 + (-6*t*(1-t) + 3*(1-t)**2)*h1 + (-3*(t**2) + 6*t*(1-t))*h2 + (3*t**2)*p2).normalized()
+ return (
+ (-3 * (1 - t)**2) * p1 + (-6 * t * (1 - t) + 3 * (1 - t)**2) * h1 +
+ (-3 * (t**2) + 6 * t * (1 - t)) * h2 + (3 * t**2) * p2
+ ).normalized()
+
# Determine the range of t values along a splines length where child stems are formed
def findChildPoints(stemList, numChild):
numPoints = sum([len(n.spline.bezier_points) for n in stemList])
numSplines = len(stemList)
numSegs = numPoints - numSplines
- numPerSeg = numChild/numSegs
- numMain = round(numPerSeg*stemList[0].segMax, 0)
- return [(a+1)/(numMain) for a in range(int(numMain))]
+ numPerSeg = numChild / numSegs
+ numMain = round(numPerSeg * stemList[0].segMax, 0)
+ return [(a + 1) / (numMain) for a in range(int(numMain))]
+
def findChildPoints2(stemList, numChild):
- return [(a+1)/(numChild) for a in range(int(numChild))]
+ return [(a + 1) / (numChild) for a in range(int(numChild))]
+
# Find the coordinates, quaternion and radius for each t on the stem
def interpStem1(stem, tVals, lPar, parRad):
@@ -210,27 +232,42 @@ def interpStem1(stem, tVals, lPar, parRad):
tempList = deque()
for t in tVals:
if t == 1.0:
- index = numPoints-2
+ index = numPoints - 2
coord = points[-1].co
quat = (points[-1].handle_right - points[-1].co).to_track_quat('Z', 'Y')
radius = points[-1].radius
- tempList.append(childPoint(coord, quat, (parRad, radius), t, lPar, 'bone'+(str(stem.splN).rjust(3, '0'))+'.'+(str(index).rjust(3, '0'))))
+ tempList.append(
+ childPoint(coord, quat, (parRad, radius), t, lPar, 'bone' +
+ (str(stem.splN).rjust(3, '0')) + '.' + (str(index).rjust(3, '0')))
+ )
elif (t >= checkVal) and (t < 1.0):
scaledT = (t - checkVal) / ((1 - checkVal) + .0001)
- length = (numPoints-1)*scaledT
+ length = (numPoints - 1) * scaledT
index = int(length)
tTemp = length - index
- coord = evalBez(points[index].co, points[index].handle_right, points[index+1].handle_left, points[index+1].co, tTemp)
- quat = (evalBezTan(points[index].co, points[index].handle_right, points[index+1].handle_left, points[index+1].co, tTemp)).to_track_quat('Z', 'Y')
- radius = (1-tTemp)*points[index].radius + tTemp*points[index+1].radius # Not sure if this is the parent radius at the child point or parent start radius
-
- tempList.append(childPoint(coord, quat, (parRad, radius), t, lPar, 'bone'+(str(stem.splN).rjust(3, '0'))+'.'+(str(index).rjust(3, '0'))))
-
+ coord = evalBez(
+ points[index].co, points[index].handle_right,
+ points[index + 1].handle_left, points[index + 1].co, tTemp
+ )
+ quat = (
+ evalBezTan(
+ points[index].co, points[index].handle_right,
+ points[index + 1].handle_left, points[index + 1].co, tTemp)
+ ).to_track_quat('Z', 'Y')
+ # Not sure if this is the parent radius at the child point or parent start radius
+ radius = (1 - tTemp) * points[index].radius + tTemp * points[index + 1].radius
+
+ tempList.append(
+ childPoint(
+ coord, quat, (parRad, radius), t, lPar, 'bone' +
+ (str(stem.splN).rjust(3, '0')) + '.' + (str(index).rjust(3, '0')))
+ )
return tempList
+
def interpStem(stem, tVals, lPar, parRad, maxOffset, baseSize):
points = stem.spline.bezier_points
numSegs = len(points) - 1
@@ -250,21 +287,40 @@ def interpStem(stem, tVals, lPar, parRad, maxOffset, baseSize):
index = int(length)
tTemp = length - index
- coord = evalBez(points[index].co, points[index].handle_right, points[index+1].handle_left, points[index+1].co, tTemp)
- quat = (evalBezTan(points[index].co, points[index].handle_right, points[index+1].handle_left, points[index+1].co, tTemp)).to_track_quat('Z', 'Y')
- radius = (1-tTemp)*points[index].radius + tTemp*points[index+1].radius # Not sure if this is the parent radius at the child point or parent start radius
-
- tempList.append(childPoint(coord, quat, (parRad, radius), t, ofst, lPar, 'bone'+(str(stem.splN).rjust(3, '0'))+'.'+(str(index).rjust(3, '0'))))
-
- #add stem at tip
- index = numSegs-1
+ coord = evalBez(
+ points[index].co, points[index].handle_right,
+ points[index + 1].handle_left, points[index + 1].co, tTemp
+ )
+ quat = (
+ evalBezTan(
+ points[index].co, points[index].handle_right,
+ points[index + 1].handle_left, points[index + 1].co, tTemp
+ )
+ ).to_track_quat('Z', 'Y')
+ # Not sure if this is the parent radius at the child point or parent start radius
+ radius = (1 - tTemp) * points[index].radius + tTemp * points[index + 1].radius
+
+ tempList.append(
+ childPoint(
+ coord, quat, (parRad, radius), t, ofst, lPar,
+ 'bone' + (str(stem.splN).rjust(3, '0')) + '.' + (str(index).rjust(3, '0')))
+ )
+
+ # add stem at tip
+ index = numSegs - 1
coord = points[-1].co
quat = (points[-1].handle_right - points[-1].co).to_track_quat('Z', 'Y')
radius = points[-1].radius
- tempList.append(childPoint(coord, quat, (parRad, radius), 1, 1, lPar, 'bone'+(str(stem.splN).rjust(3, '0'))+'.'+(str(index).rjust(3, '0'))))
+ tempList.append(
+ childPoint(
+ coord, quat, (parRad, radius), 1, 1, lPar,
+ 'bone' + (str(stem.splN).rjust(3, '0')) + '.' + (str(index).rjust(3, '0'))
+ )
+ )
return tempList
+
# round down bone number
def roundBone(bone, step):
bone_i = bone[:-3]
@@ -272,10 +328,12 @@ def roundBone(bone, step):
bone_n = int(bone_n / step) * step
return bone_i + str(bone_n).rjust(3, '0')
+
# Convert a list of degrees to radians
def toRad(list):
return [radians(a) for a in list]
+
def anglemean(a1, a2, fac):
x1 = sin(a1)
y1 = cos(a1)
@@ -287,16 +345,17 @@ def anglemean(a1, a2, fac):
# This is the function which extends (or grows) a given stem.
-def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, splineToBone, closeTip, kp, splitHeight, outAtt, stemsegL,
+def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList,
+ hType, splineToBone, closeTip, kp, splitHeight, outAtt, stemsegL,
lenVar, taperCrown, boneStep, rotate, rotateV):
- #curv at base
+ # curv at base
sCurv = stem.curv
if (n == 0) and (kp <= splitHeight):
sCurv = 0.0
- #curveangle = sCurv + (uniform(-stem.curvV, stem.curvV) * kp)
- #curveVar = uniform(-stem.curvV, stem.curvV) * kp
+ # curveangle = sCurv + (uniform(-stem.curvV, stem.curvV) * kp)
+ # curveVar = uniform(-stem.curvV, stem.curvV) * kp
curveangle = sCurv + (uniform(0, stem.curvV) * kp * stem.curvSignx)
curveVar = uniform(0, stem.curvV) * kp * stem.curvSigny
stem.curvSignx *= -1
@@ -317,7 +376,7 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
dir = Euler((-rx, ry, 0), 'XYZ')
- #length taperCrown
+ # length taperCrown
if n == 0:
dec = declination(dir) / 180
dec = dec ** 2
@@ -326,7 +385,7 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
else:
tf = 1.0
- #outward attraction
+ # outward attraction
if (n > 0) and (kp > 0) and (outAtt > 0):
p = stem.p.co.copy()
d = atan2(p[0], -p[1]) + tau
@@ -334,23 +393,24 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
d = anglemean(edir[2], d, (kp * outAtt))
dirv = Euler((edir[0], edir[1], d), 'XYZ')
dir = dirv.to_quaternion()
-
- #parent weight
-# parWeight = kp * degrees(stem.curvV) * pi
-# #parWeight = parWeight * kp
-# #parWeight = kp
-# if (n > 1) and (parWeight != 0):
-# d1 = zAxis.copy()
-# d2 = zAxis.copy()
-# d1.rotate(dir)
-# d2.rotate(stem.patentQuat)
-#
-# x = d1[0] + ((d2[0] - d1[0]) * parWeight)
-# y = d1[1] + ((d2[1] - d1[1]) * parWeight)
-# z = d1[2] + ((d2[2] - d1[2]) * parWeight)
-#
-# d3 = Vector((x, y, z))
-# dir = d3.to_track_quat('Z', 'Y')
+ """
+ # parent weight
+ parWeight = kp * degrees(stem.curvV) * pi
+ parWeight = parWeight * kp
+ parWeight = kp
+ if (n > 1) and (parWeight != 0):
+ d1 = zAxis.copy()
+ d2 = zAxis.copy()
+ d1.rotate(dir)
+ d2.rotate(stem.patentQuat)
+
+ x = d1[0] + ((d2[0] - d1[0]) * parWeight)
+ y = d1[1] + ((d2[1] - d1[1]) * parWeight)
+ z = d1[2] + ((d2[2] - d1[2]) * parWeight)
+
+ d3 = Vector((x, y, z))
+ dir = d3.to_track_quat('Z', 'Y')
+ """
# If the stem splits, we need to add new splines etc
if numSplit > 0:
@@ -358,14 +418,14 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
cuData = stem.spline.id_data.name
cu = bpy.data.curves[cuData]
- #calc split angles
+ # calc split angles
angle = choice([-1, 1]) * (splitAng + uniform(-splitAngV, splitAngV))
if n > 0:
- #make branches flatter
+ # make branches flatter
angle *= max(1 - declination(dir) / 90, 0) * .67 + .33
spreadangle = choice([-1, 1]) * (splitAng + uniform(-splitAngV, splitAngV))
- #branchRotMat = Matrix.Rotation(radians(uniform(0, 360)), 3, 'Z')
+ # branchRotMat = Matrix.Rotation(radians(uniform(0, 360)), 3, 'Z')
if not hasattr(stem, 'rLast'):
stem.rLast = radians(uniform(0, 360))
@@ -376,31 +436,33 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
# Now for each split add the new spline and adjust the growth direction
for i in range(numSplit):
- #find split scale
+ # find split scale
lenV = uniform(1 - lenVar, 1 + lenVar)
bScale = min(lenV * tf, 1)
newSpline = cu.splines.new('BEZIER')
newPoint = newSpline.bezier_points[-1]
(newPoint.co, newPoint.handle_left_type, newPoint.handle_right_type) = (stem.p.co, 'VECTOR', 'VECTOR')
- newPoint.radius = (stem.radS*(1 - stem.seg/stem.segMax) + stem.radE*(stem.seg/stem.segMax)) * bScale
+ newPoint.radius = (
+ stem.radS * (1 - stem.seg / stem.segMax) + stem.radE * (stem.seg / stem.segMax)
+ ) * bScale
# Here we make the new "sprouting" stems diverge from the current direction
divRotMat = Matrix.Rotation(angle + curveangle, 3, 'X')
dirVec = zAxis.copy()
dirVec.rotate(divRotMat)
- #horizontal curvature variation
+ # horizontal curvature variation
dirVec.rotate(curveVarMat)
- if n == 0: #Special case for trunk splits
+ if n == 0: # Special case for trunk splits
dirVec.rotate(branchRotMat)
- ang = pi - ((tau) / (numSplit + 1)) * (i+1)
+ ang = pi - ((tau) / (numSplit + 1)) * (i + 1)
dirVec.rotate(Matrix.Rotation(ang, 3, 'Z'))
# Spread the stem out in a random fashion
spreadMat = Matrix.Rotation(spreadangle, 3, 'Y')
- if n != 0: #Special case for trunk splits
+ if n != 0: # Special case for trunk splits
dirVec.rotate(spreadMat)
dirVec.rotate(dir)
@@ -415,12 +477,12 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
# Make the growth vec the length of a stem segment
dirVec.normalize()
- #split length variation
+ # split length variation
stemL = stemsegL * lenV
dirVec *= stemL * tf
ofst = stem.offsetLen + (stem.segL * (len(stem.spline.bezier_points) - 1))
- ##dirVec *= stem.segL
+ # dirVec *= stem.segL
# Get the end point position
end_co = stem.p.co.copy()
@@ -429,40 +491,48 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
newSpline.bezier_points.add()
newPoint = newSpline.bezier_points[-1]
(newPoint.co, newPoint.handle_left_type, newPoint.handle_right_type) = (end_co + dirVec, hType, hType)
- newPoint.radius = (stem.radS*(1 - (stem.seg + 1)/stem.segMax) + stem.radE*((stem.seg + 1)/stem.segMax)) * bScale
- if (stem.seg == stem.segMax-1) and closeTip:
+ newPoint.radius = (
+ stem.radS * (1 - (stem.seg + 1) / stem.segMax) +
+ stem.radE * ((stem.seg + 1) / stem.segMax)
+ ) * bScale
+ if (stem.seg == stem.segMax - 1) and closeTip:
newPoint.radius = 0.0
- # If this isn't the last point on a stem, then we need to add it to the list of stems to continue growing
- #print(stem.seg != stem.segMax, stem.seg, stem.segMax)
- #if stem.seg != stem.segMax: # if probs not nessesary
- nstem = stemSpline(newSpline, stem.curv, stem.curvV, stem.vertAtt, stem.seg+1, stem.segMax, stemL, stem.children,
- stem.radS * bScale, stem.radE * bScale, len(cu.splines)-1, ofst, stem.quat())
- nstem.splitlast = 1#numSplit #keep track of numSplit for next stem
+ # If this isn't the last point on a stem, then we need to add it
+ # to the list of stems to continue growing
+ # print(stem.seg != stem.segMax, stem.seg, stem.segMax)
+ # if stem.seg != stem.segMax: # if probs not nessesary
+ nstem = stemSpline(
+ newSpline, stem.curv, stem.curvV, stem.vertAtt, stem.seg + 1,
+ stem.segMax, stemL, stem.children,
+ stem.radS * bScale, stem.radE * bScale, len(cu.splines) - 1, ofst, stem.quat()
+ )
+ nstem.splitlast = 1 # numSplit # keep track of numSplit for next stem
nstem.rLast = branchRot + pi
splineList.append(nstem)
- bone = 'bone'+(str(stem.splN)).rjust(3, '0')+'.'+(str(len(stem.spline.bezier_points)-2)).rjust(3, '0')
+ bone = 'bone' + (str(stem.splN)).rjust(3, '0') + '.' + \
+ (str(len(stem.spline.bezier_points) - 2)).rjust(3, '0')
bone = roundBone(bone, boneStep[n])
- splineToBone.append((bone, False, True, len(stem.spline.bezier_points)-2))
+ splineToBone.append((bone, False, True, len(stem.spline.bezier_points) - 2))
# The original spline also needs to keep growing so adjust its direction too
divRotMat = Matrix.Rotation(-angle + curveangle, 3, 'X')
dirVec = zAxis.copy()
dirVec.rotate(divRotMat)
- #horizontal curvature variation
+ # horizontal curvature variation
dirVec.rotate(curveVarMat)
- if n == 0: #Special case for trunk splits
+ if n == 0: # Special case for trunk splits
dirVec.rotate(branchRotMat)
- #spread
+ # spread
spreadMat = Matrix.Rotation(-spreadangle, 3, 'Y')
- if n != 0: #Special case for trunk splits
+ if n != 0: # Special case for trunk splits
dirVec.rotate(spreadMat)
dirVec.rotate(dir)
- stem.splitlast = 1#numSplit #keep track of numSplit for next stem
+ stem.splitlast = 1 # numSplit #keep track of numSplit for next stem
else:
# If there are no splits then generate the growth direction without accounting for spreading of stems
@@ -470,12 +540,12 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
divRotMat = Matrix.Rotation(curveangle, 3, 'X')
dirVec.rotate(divRotMat)
- #horizontal curvature variation
+ # horizontal curvature variation
dirVec.rotate(curveVarMat)
dirVec.rotate(dir)
- stem.splitlast = 0#numSplit #keep track of numSplit for next stem
+ stem.splitlast = 0 # numSplit #keep track of numSplit for next stem
# Introduce upward curvature
upRotAxis = xAxis.copy()
@@ -493,25 +563,32 @@ def growSpline(n, stem, numSplit, splitAng, splitAngV, splineList, hType, spline
stem.spline.bezier_points.add()
newPoint = stem.spline.bezier_points[-1]
(newPoint.co, newPoint.handle_left_type, newPoint.handle_right_type) = (end_co + dirVec, hType, hType)
- newPoint.radius = stem.radS*(1 - (stem.seg + 1)/stem.segMax) + stem.radE*((stem.seg + 1)/stem.segMax)
- if (stem.seg == stem.segMax-1) and closeTip:
+ newPoint.radius = stem.radS * (1 - (stem.seg + 1) / stem.segMax) + \
+ stem.radE * ((stem.seg + 1) / stem.segMax)
+
+ if (stem.seg == stem.segMax - 1) and closeTip:
newPoint.radius = 0.0
- # There are some cases where a point cannot have handles as VECTOR straight away, set these now.
+ # There are some cases where a point cannot have handles as VECTOR straight away, set these now
if len(stem.spline.bezier_points) == 2:
tempPoint = stem.spline.bezier_points[0]
(tempPoint.handle_left_type, tempPoint.handle_right_type) = ('VECTOR', 'VECTOR')
# Update the last point in the spline to be the newly added one
stem.updateEnd()
- #return splineList
+ # return splineList
+
-def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset, index, downAngle, downAngleV, rotate, rotateV, oldRot,
+def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat,
+ offset, index, downAngle, downAngleV, rotate, rotateV, oldRot,
bend, leaves, leafShape, leafangle, horzLeaves):
if leafShape == 'hex':
- verts = [Vector((0, 0, 0)), Vector((0.5, 0, 1/3)), Vector((0.5, 0, 2/3)), Vector((0, 0, 1)), Vector((-0.5, 0, 2/3)), Vector((-0.5, 0, 1/3))]
+ verts = [
+ Vector((0, 0, 0)), Vector((0.5, 0, 1 / 3)), Vector((0.5, 0, 2 / 3)),
+ Vector((0, 0, 1)), Vector((-0.5, 0, 2 / 3)), Vector((-0.5, 0, 1 / 3))
+ ]
edges = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0], [0, 3]]
faces = [[0, 1, 2, 3], [0, 3, 4, 5]]
elif leafShape == 'rect':
- #verts = [Vector((1, 0, 0)), Vector((1, 0, 1)), Vector((-1, 0, 1)), Vector((-1, 0, 0))]
+ # verts = [Vector((1, 0, 0)), Vector((1, 0, 1)), Vector((-1, 0, 1)), Vector((-1, 0, 0))]
verts = [Vector((.5, 0, 0)), Vector((.5, 0, 1)), Vector((-.5, 0, 1)), Vector((-.5, 0, 0))]
edges = [[0, 1], [1, 2], [2, 3], [3, 0]]
faces = [[0, 1, 2, 3]]
@@ -533,26 +610,27 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
else:
rotMat = Matrix.Rotation(oldRot, 3, 'Z')
- # If the -ve flag for rotate is used we need to find which side of the stem the last child point was and then grow in the opposite direction.
+ # If the -ve flag for rotate is used we need to find which side of the stem
+ # the last child point was and then grow in the opposite direction
if rotate < 0.0:
oldRot = -copysign(rotate + uniform(-rotateV, rotateV), oldRot)
else:
# If the special -ve flag for leaves is used we need a different rotation of the leaf geometry
if leaves == -1:
- #oldRot = 0
+ # oldRot = 0
rotMat = Matrix.Rotation(0, 3, 'Y')
elif leaves < -1:
oldRot += rotate / (-leaves - 1)
else:
oldRot += rotate + uniform(-rotateV, rotateV)
-
-# if leaves < 0:
-# rotMat = Matrix.Rotation(oldRot, 3, 'Y')
-# else:
-# rotMat = Matrix.Rotation(oldRot, 3, 'Z')
-
+ """
+ if leaves < 0:
+ rotMat = Matrix.Rotation(oldRot, 3, 'Y')
+ else:
+ rotMat = Matrix.Rotation(oldRot, 3, 'Z')
+ """
if leaves >= 0:
- #downRotMat = Matrix.Rotation(downAngle+uniform(-downAngleV, downAngleV), 3, 'X')
+ # downRotMat = Matrix.Rotation(downAngle+uniform(-downAngleV, downAngleV), 3, 'X')
if downAngleV > 0.0:
downV = -downAngleV * offset
@@ -560,7 +638,7 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
downV = uniform(-downAngleV, downAngleV)
downRotMat = Matrix.Rotation(downAngle + downV, 3, 'X')
- #leaf scale variation
+ # leaf scale variation
if (leaves < -1) and (rotate != 0):
f = 1 - abs((oldRot - (rotate / (-leaves - 1))) / (rotate / 2))
else:
@@ -586,7 +664,7 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
thetaPos = atan2(loc.y, loc.x)
thetaBend = thetaPos - atan2(normal.y, normal.x)
- rotateZ = Matrix.Rotation(bend*thetaBend, 3, 'Z')
+ rotateZ = Matrix.Rotation(bend * thetaBend, 3, 'Z')
normal.rotate(rotateZ)
orientationVec.rotate(rotateZ)
@@ -594,7 +672,7 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
orientation = atan2(orientationVec.y, orientationVec.x)
rotateZOrien = Matrix.Rotation(orientation, 3, 'X')
- rotateX = Matrix.Rotation(bend*phiBend, 3, 'Z')
+ rotateX = Matrix.Rotation(bend * phiBend, 3, 'Z')
rotateZOrien2 = Matrix.Rotation(-orientation, 3, 'X')
@@ -602,11 +680,11 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
for v in verts:
v.z *= leafScale
v.y *= leafScale
- v.x *= leafScaleX*leafScale
+ v.x *= leafScaleX * leafScale
v.rotate(Euler((0, 0, radians(180))))
- #leafangle
+ # leafangle
v.rotate(Matrix.Rotation(radians(-leafangle), 3, 'X'))
if rotate < 0:
@@ -646,8 +724,9 @@ def genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, loc, quat, offset
return vertsList, facesList, normal, oldRot
-def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSize, leaves, levelCount, splineToBone,
- treeOb, wind, gust, gustF, af1, af2, af3, leafAnim, loopFrames, previewArm, armLevels, makeMesh, boneStep):
+def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSize, leaves,
+ levelCount, splineToBone, treeOb, wind, gust, gustF, af1, af2, af3,
+ leafAnim, loopFrames, previewArm, armLevels, makeMesh, boneStep):
arm = bpy.data.armatures.new('tree')
armOb = bpy.data.objects.new('treeArm', arm)
bpy.context.scene.objects.link(armOb)
@@ -666,7 +745,7 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
armMod.use_apply_on_spline = True
armMod.object = armOb
armMod.use_bone_envelopes = True
- armMod.use_vertex_groups = False # curves don't have vertex groups (yet)
+ armMod.use_vertex_groups = False # curves don't have vertex groups (yet)
# If there are leaves then they need a modifier
if leaves:
armMod = leafObj.modifiers.new('windSway', 'ARMATURE')
@@ -691,7 +770,7 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
# Get some data about the spline like length and number of points
numPoints = len(s.bezier_points) - 1
- #find branching level
+ # find branching level
level = 0
for l, c in enumerate(levelCount):
if i < c:
@@ -708,10 +787,11 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
bxOffset = uniform(0, tau)
byOffset = uniform(0, tau)
# Set the phase multiplier for the spline
- #bMult_r = (s.bezier_points[0].radius / max(splineL, 1e-6)) * (1 / 15) * (1 / frameRate)
- #bMult = degrees(bMult_r) # This shouldn't have to be in degrees but it looks much better in animation
+ # bMult_r = (s.bezier_points[0].radius / max(splineL, 1e-6)) * (1 / 15) * (1 / frameRate)
+ # This shouldn't have to be in degrees but it looks much better in animation
+ # bMult = degrees(bMult_r)
bMult = (1 / max(splineL ** .5, 1e-6)) * (1 / 4)
- #print((1 / bMult) * tau) #print wavelength in frames
+ # print((1 / bMult) * tau) #print wavelength in frames
windFreq1 = bMult * animSpeed
windFreq2 = 0.7 * bMult * animSpeed
@@ -736,14 +816,14 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
b.head_radius = s.bezier_points[n].radius
b.tail_radius = s.bezier_points[n + 1].radius
b.envelope_distance = 0.001
-
-# # If there are leaves then we need a new vertex group so they will attach to the bone
-# if not leafAnim:
-# if (len(levelCount) > 1) and (i >= levelCount[-2]) and leafObj:
-# leafObj.vertex_groups.new(boneName)
-# elif (len(levelCount) == 1) and leafObj:
-# leafObj.vertex_groups.new(boneName)
-
+ """
+ # If there are leaves then we need a new vertex group so they will attach to the bone
+ if not leafAnim:
+ if (len(levelCount) > 1) and (i >= levelCount[-2]) and leafObj:
+ leafObj.vertex_groups.new(boneName)
+ elif (len(levelCount) == 1) and leafObj:
+ leafObj.vertex_groups.new(boneName)
+ """
# If this is first point of the spline then it must be parented to the level above it
if n == 0:
if parBone:
@@ -759,12 +839,12 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
# Add the animation to the armature if required
if armAnim:
# Define all the required parameters of the wind sway by the dimension of the spline
- #a0 = 4 * splineL * (1 - n / (numPoints + 1)) / max(s.bezier_points[n].radius, 1e-6)
+ # a0 = 4 * splineL * (1 - n / (numPoints + 1)) / max(s.bezier_points[n].radius, 1e-6)
a0 = 2 * (splineL / numPoints) * (1 - n / (numPoints + 1)) / max(s.bezier_points[n].radius, 1e-6)
a0 = a0 * min(step, numPoints)
- #a0 = (splineL / numPoints) / max(s.bezier_points[n].radius, 1e-6)
+ # a0 = (splineL / numPoints) / max(s.bezier_points[n].radius, 1e-6)
a1 = (wind / 50) * a0
- a2 = a1 * .65 #(windGust / 50) * a0 + a1 / 2
+ a2 = a1 * .65 # (windGust / 50) * a0 + a1 / 2
p = s.bezier_points[nx].co - s.bezier_points[n].co
p.normalize()
@@ -777,9 +857,9 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
a3 = radians(a3)
a4 = radians(a4)
- #wind bending
+ # wind bending
if loopFrames == 0:
- swayFreq = gustF * (tau / fps) * frameRate #animSpeed # .075 # 0.02
+ swayFreq = gustF * (tau / fps) * frameRate # animSpeed # .075 # 0.02
else:
swayFreq = 1 / (loopFrames / tau)
@@ -791,9 +871,12 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
a4 = 0
# Add new fcurves for each sway as well as the modifiers
- swayX = armOb.animation_data.action.fcurves.new('pose.bones["' + boneName + '"].rotation_euler', 0)
- swayY = armOb.animation_data.action.fcurves.new('pose.bones["' + boneName + '"].rotation_euler', 2)
-
+ swayX = armOb.animation_data.action.fcurves.new(
+ 'pose.bones["' + boneName + '"].rotation_euler', 0
+ )
+ swayY = armOb.animation_data.action.fcurves.new(
+ 'pose.bones["' + boneName + '"].rotation_euler', 2
+ )
swayXMod1 = swayX.modifiers.new(type='FNGENERATOR')
swayXMod2 = swayX.modifiers.new(type='FNGENERATOR')
@@ -819,7 +902,7 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
swayYMod2.phase_multiplier = windFreq2
swayYMod2.use_additive = True
- #wind bending
+ # wind bending
swayYMod3 = swayY.modifiers.new(type='FNGENERATOR')
swayYMod3.amplitude = a3
swayYMod3.phase_multiplier = swayFreq
@@ -840,7 +923,7 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
leafParent = roundBone(cp.parBone, boneStep[armLevels])
idx = int(leafParent[4:-4])
while leafParent not in bonelist:
- #find parent bone of parent bone
+ # find parent bone of parent bone
leafParent = splineToBone[idx]
idx = int(leafParent[4:-4])
@@ -852,7 +935,10 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
b.envelope_distance = 0.0
b.parent = arm.edit_bones[leafParent]
- vertexGroups[bname] = [v.index for v in leafMesh.vertices[leafVertSize * i:(leafVertSize * i + leafVertSize)]]
+ vertexGroups[bname] = [
+ v.index for v in
+ leafMesh.vertices[leafVertSize * i:(leafVertSize * i + leafVertSize)]
+ ]
if armAnim:
# Define all the required parameters of the wind sway by the dimension of the spline
@@ -867,9 +953,12 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
byOffset = uniform(-ofstRand, ofstRand)
# Add new fcurves for each sway as well as the modifiers
- swayX = armOb.animation_data.action.fcurves.new('pose.bones["' + bname + '"].rotation_euler', 0)
- swayY = armOb.animation_data.action.fcurves.new('pose.bones["' + bname + '"].rotation_euler', 2)
-
+ swayX = armOb.animation_data.action.fcurves.new(
+ 'pose.bones["' + bname + '"].rotation_euler', 0
+ )
+ swayY = armOb.animation_data.action.fcurves.new(
+ 'pose.bones["' + bname + '"].rotation_euler', 2
+ )
# Add keyframe so noise works
swayX.keyframe_points.add()
swayY.keyframe_points.add()
@@ -901,7 +990,10 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
else:
if leafParent not in vertexGroups:
vertexGroups[leafParent] = []
- vertexGroups[leafParent].extend([v.index for v in leafMesh.vertices[leafVertSize * i:(leafVertSize * i + leafVertSize)]])
+ vertexGroups[leafParent].extend(
+ [v.index for v in
+ leafMesh.vertices[leafVertSize * i:(leafVertSize * i + leafVertSize)]]
+ )
for group in vertexGroups:
leafObj.vertex_groups.new(group)
@@ -914,8 +1006,9 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi
treeOb.parent = armOb
-def kickstart_trunk(addstem, levels, leaves, branches, cu, curve, curveRes, curveV, attractUp, length, lengthV, ratio, ratioPower, resU, scale0, scaleV0,
- scaleVal, taper, minRadius, rootFlare):
+def kickstart_trunk(addstem, levels, leaves, branches, cu, curve, curveRes,
+ curveV, attractUp, length, lengthV, ratio, ratioPower,
+ resU, scale0, scaleV0, scaleVal, taper, minRadius, rootFlare):
newSpline = cu.splines.new('BEZIER')
cu.resolution_u = resU
newPoint = newSpline.bezier_points[-1]
@@ -925,33 +1018,38 @@ def kickstart_trunk(addstem, levels, leaves, branches, cu, curve, curveRes, curv
# (newPoint.handle_right_type, newPoint.handle_left_type) = ('VECTOR', 'VECTOR')
branchL = scaleVal * length[0]
curveVal = curve[0] / curveRes[0]
- #curveVal = curveVal * (branchL / scaleVal)
+ # curveVal = curveVal * (branchL / scaleVal)
if levels == 1:
childStems = leaves
else:
childStems = branches[1]
- startRad = scaleVal * ratio * scale0 * uniform(1-scaleV0, 1+scaleV0) ## * (scale0 + uniform(-scaleV0, scaleV0)) #
+ startRad = scaleVal * ratio * scale0 * uniform(1 - scaleV0, 1 + scaleV0) # * (scale0 + uniform(-scaleV0, scaleV0))
endRad = (startRad * (1 - taper[0])) ** ratioPower
startRad = max(startRad, minRadius)
endRad = max(endRad, minRadius)
newPoint.radius = startRad * rootFlare
addstem(
- stemSpline(newSpline, curveVal, curveV[0] / curveRes[0], attractUp[0], 0, curveRes[0], branchL / curveRes[0],
- childStems, startRad, endRad, 0, 0, None))
-
-
-def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, curve, curveBack, curveRes, curveV, attractUp,
- downAngle, downAngleV, leafDist, leaves, length, lengthV, levels, n, ratioPower, resU,
- rotate, rotateV, scaleVal, shape, storeN, taper, shapeS, minRadius, radiusTweak, customShape, rMode, segSplits,
+ stemSpline(
+ newSpline, curveVal, curveV[0] / curveRes[0], attractUp[0],
+ 0, curveRes[0], branchL / curveRes[0],
+ childStems, startRad, endRad, 0, 0, None
+ )
+ )
+
+
+def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, curve, curveBack,
+ curveRes, curveV, attractUp, downAngle, downAngleV, leafDist, leaves, length,
+ lengthV, levels, n, ratioPower, resU, rotate, rotateV, scaleVal, shape, storeN,
+ taper, shapeS, minRadius, radiusTweak, customShape, rMode, segSplits,
useOldDownAngle, useParentAngle, boneStep):
- #prevent baseSize from going to 1.0
+ # prevent baseSize from going to 1.0
baseSize = min(0.999, baseSize)
# Store the old rotation to allow new stems to be rotated away from the previous one.
oldRotate = 0
- #use fancy child point selection / rotation
+ # use fancy child point selection / rotation
if (n == 1) and (rMode != "original"):
childP_T = OrderedDict()
childP_L = []
@@ -976,17 +1074,17 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
oldRotate += rotate[n]
bRotate = oldRotate + uniform(-rotateV[n], rotateV[n])
- #choose start point whose angle is closest to the rotate angle
+ # choose start point whose angle is closest to the rotate angle
a1 = bRotate % tau
a_diff = []
for a in p:
a2 = atan2(a.co[0], -a.co[1])
- d = min((a1-a2+tau)%tau, (a2-a1+tau)%tau)
+ d = min((a1 - a2 + tau) % tau, (a2 - a1 + tau) % tau)
a_diff.append(d)
idx = a_diff.index(min(a_diff))
- #find actual rotate angle from branch location
+ # find actual rotate angle from branch location
br = p[idx]
b = br.co
vx = sin(bRotate)
@@ -996,7 +1094,7 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
bD = ((b[0] * b[0] + b[1] * b[1]) ** .5)
bL = br.lengthPar * length[1] * shapeRatio(shape, (1 - br.offset) / (1 - baseSize), custom=customShape)
- #account for down angle
+ # account for down angle
if downAngleV[1] > 0:
downA = downAngle[n] + (-downAngleV[n] * (1 - (1 - br.offset) / (1 - baseSize)) ** 2)
else:
@@ -1011,27 +1109,27 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
bv = Vector((b[0], -b[1]))
cv = v - bv
a = atan2(cv[0], cv[1])
- #rot_a.append(a)
-
-# # add fill points at top #experimental
-# fillHeight = 1 - degrees(rotateV[3])#0.8
-# if fillHeight < 1:
-# w = (p[0].offset - fillHeight) / (1- fillHeight)
-# prob_b = random() < w
-# else:
-# prob_b = False
-#
-# if (p[0].offset > fillHeight): #prob_b and (len(p) > 1): ##(p[0].offset > fillHeight) and
-# childP.append(p[randint(0, len(p)-1)])
-# rot_a.append(bRotate)# + pi)
+ # rot_a.append(a)
+ """
+ # add fill points at top #experimental
+ fillHeight = 1 - degrees(rotateV[3]) # 0.8
+ if fillHeight < 1:
+ w = (p[0].offset - fillHeight) / (1- fillHeight)
+ prob_b = random() < w
+ else:
+ prob_b = False
+ if (p[0].offset > fillHeight): # prob_b and (len(p) > 1): ##(p[0].offset > fillHeight) and
+ childP.append(p[randint(0, len(p)-1)])
+ rot_a.append(bRotate)# + pi)
+ """
childP.append(p[idx])
rot_a.append(a)
else:
- idx = randint(0, len(p)-1)
+ idx = randint(0, len(p) - 1)
childP.append(p[idx])
- #childP.append(p[idx])
+ # childP.append(p[idx])
childP.extend(childP_L)
rot_a.extend([0] * len(childP_L))
@@ -1056,14 +1154,15 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
if downAngleV[n] < 0.0:
downV = uniform(-downAngleV[n], downAngleV[n])
else:
- downV = -downAngleV[n] * (1 - (1 - p.offset) / (1 - baseSize)) ** 2 #(110, 80) = (60, -50)
+ downV = -downAngleV[n] * (1 - (1 - p.offset) / (1 - baseSize)) ** 2 # (110, 80) = (60, -50)
if p.offset == 1:
downRotMat = Matrix.Rotation(0, 3, 'X')
else:
downRotMat = Matrix.Rotation(downAngle[n] + downV, 3, 'X')
- # If the -ve flag for rotate is used we need to find which side of the stem the last child point was and then grow in the opposite direction.
+ # If the -ve flag for rotate is used we need to find which side of the stem
+ # the last child point was and then grow in the opposite direction
if rotate[n] < 0.0:
oldRotate = -copysign(rotate[n], oldRotate)
# Otherwise just generate a random number in the specified range
@@ -1080,7 +1179,7 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
tempPos.rotate(downRotMat)
tempPos.rotate(rotMat)
- #use quat angle
+ # use quat angle
if (rMode == "rotate") and (n == 1) and (p.offset != 1):
if useParentAngle:
edir = p.quat.to_euler('XYZ', Euler((0, 0, bRotate), 'XYZ'))
@@ -1101,13 +1200,13 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
newPoint.handle_right = p.co + tempPos
# Make length variation inversely proportional to segSplits
- #lenV = (1 - min(segSplits[n], 1)) * lengthV[n]
+ # lenV = (1 - min(segSplits[n], 1)) * lengthV[n]
# Find branch length and the number of child stems.
maxbL = scaleVal
- for l in length[:n+1]:
+ for l in length[:n + 1]:
maxbL *= l
- lMax = length[n] # * uniform(1 - lenV, 1 + lenV)
+ lMax = length[n] # * uniform(1 - lenV, 1 + lenV)
if n == 1:
lShape = shapeRatio(shape, (1 - p.stemOffset) / (1 - baseSize), custom=customShape)
else:
@@ -1122,7 +1221,7 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
else:
childStems = leaves * (0.1 + 0.9 * (branchL / maxbL)) * shapeRatio(leafDist, (1 - p.offset))
- #print("n=%d, levels=%d, n'=%d, childStems=%s"%(n, levels, storeN, childStems))
+ # print("n=%d, levels=%d, n'=%d, childStems=%s"%(n, levels, storeN, childStems))
# Determine the starting and ending radii of the stem using the tapering of the stem
startRad = min((p.radiusPar[0] * ((branchL / p.lengthPar) ** ratioPower)) * radiusTweak[n], p.radiusPar[1])
@@ -1137,14 +1236,18 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
curveVal = curve[n] / curveRes[n]
curveVar = curveV[n] / curveRes[n]
- #curveVal = curveVal * (branchL / scaleVal)
+ # curveVal = curveVal * (branchL / scaleVal)
# Add the new stem to list of stems to grow and define which bone it will be parented to
addstem(
- stemSpline(newSpline, curveVal, curveVar, attractUp[n], 0, curveRes[n], branchL / curveRes[n], childStems,
- startRad, endRad, len(cu.splines) - 1, 0, p.quat))
-
- bone = roundBone(p.parBone, boneStep[n-1])
+ stemSpline(
+ newSpline, curveVal, curveVar, attractUp[n],
+ 0, curveRes[n], branchL / curveRes[n], childStems,
+ startRad, endRad, len(cu.splines) - 1, 0, p.quat
+ )
+ )
+
+ bone = roundBone(p.parBone, boneStep[n - 1])
if p.offset == 1:
isend = True
else:
@@ -1152,23 +1255,26 @@ def fabricate_stems(addsplinetobone, addstem, baseSize, branches, childP, cu, cu
addsplinetobone((bone, isend))
-def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, currentScale, curve, curveBack, curveRes,
- deleteSpline, forceSprout, handles, n, oldMax, orginalSplineToBone, originalCo, originalCurv,
- originalCurvV, originalHandleL, originalHandleR, originalLength, originalSeg, prune, prunePowerHigh,
- prunePowerLow, pruneRatio, pruneWidth, pruneBase, pruneWidthPeak, randState, ratio, scaleVal, segSplits,
- splineToBone, splitAngle, splitAngleV, st, startPrune, branchDist, length, splitByLen, closeTip, nrings,
- splitBias, splitHeight, attractOut, rMode, lengthV, taperCrown, boneStep, rotate, rotateV):
+def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, currentScale, curve,
+ curveBack, curveRes, deleteSpline, forceSprout, handles, n, oldMax, orginalSplineToBone,
+ originalCo, originalCurv, originalCurvV, originalHandleL, originalHandleR, originalLength,
+ originalSeg, prune, prunePowerHigh, prunePowerLow, pruneRatio, pruneWidth, pruneBase,
+ pruneWidthPeak, randState, ratio, scaleVal, segSplits, splineToBone, splitAngle, splitAngleV,
+ st, startPrune, branchDist, length, splitByLen, closeTip, nrings, splitBias, splitHeight,
+ attractOut, rMode, lengthV, taperCrown, boneStep, rotate, rotateV):
while startPrune and ((currentMax - currentMin) > 0.005):
setstate(randState)
- # If the search will halt after this iteration, then set the adjustment of stem length to take into account the pruning ratio
+ # If the search will halt after this iteration, then set the adjustment of stem
+ # length to take into account the pruning ratio
if (currentMax - currentMin) < 0.01:
currentScale = (currentScale - 1) * pruneRatio + 1
startPrune = False
forceSprout = True
# Change the segment length of the stem by applying some scaling
st.segL = originalLength * currentScale
- # To prevent millions of splines being created we delete any old ones and replace them with only their first points to begin the spline again
+ # To prevent millions of splines being created we delete any old ones and
+ # replace them with only their first points to begin the spline again
if deleteSpline:
for x in splineList:
cu.splines.remove(x.spline)
@@ -1189,9 +1295,9 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
# Initialise the spline list for those contained in the current level of branching
splineList = [st]
- #split length variation
- stemsegL = splineList[0].segL #initial segment length used for variation
- splineList[0].segL = stemsegL * uniform(1 - lengthV[n], 1 + lengthV[n]) #variation for first stem
+ # split length variation
+ stemsegL = splineList[0].segL # initial segment length used for variation
+ splineList[0].segL = stemsegL * uniform(1 - lengthV[n], 1 + lengthV[n]) # variation for first stem
# For each of the segments of the stem which must be grown we have to add to each spline in splineList
for k in range(curveRes[n]):
@@ -1199,13 +1305,13 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
tempList = splineList[:]
# print('Leng: ', len(tempList))
- #for curve variation
+ # for curve variation
if curveRes[n] > 1:
- kp = (k / (curveRes[n] - 1)) # * 2
+ kp = (k / (curveRes[n] - 1)) # * 2
else:
kp = 1.0
- #split bias
+ # split bias
splitValue = segSplits[n]
if n == 0:
splitValue = ((2 * splitBias) * (kp - .5) + 1) * splitValue
@@ -1213,8 +1319,7 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
# For each of the splines in this list set the number of splits and then grow it
for spl in tempList:
-
- #adjust numSplit
+ # adjust numSplit
lastsplit = getattr(spl, 'splitlast', 0)
splitVal = splitValue
if lastsplit == 0:
@@ -1224,17 +1329,18 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
if k == 0:
numSplit = 0
- elif (n == 0) and (k < ((curveRes[n]-1) * splitHeight)) and (k != 1):
+ elif (n == 0) and (k < ((curveRes[n] - 1) * splitHeight)) and (k != 1):
numSplit = 0
elif (k == 1) and (n == 0):
numSplit = baseSplits
- elif (n == 0) and (k == int((curveRes[n]-1) * splitHeight) + 1) and (splitVal > 0): #allways split at splitHeight
+ # allways split at splitHeight
+ elif (n == 0) and (k == int((curveRes[n] - 1) * splitHeight) + 1) and (splitVal > 0):
numSplit = 1
else:
if (n >= 1) and splitByLen:
L = ((spl.segL * curveRes[n]) / scaleVal)
lf = 1
- for l in length[:n+1]:
+ for l in length[:n + 1]:
lf *= l
L = L / lf
numSplit = splits2(splitVal * L)
@@ -1242,10 +1348,13 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
numSplit = splits2(splitVal)
if (k == int(curveRes[n] / 2 + 0.5)) and (curveBack[n] != 0):
- spl.curv += 2 * (curveBack[n] / curveRes[n]) #was -4 *
+ spl.curv += 2 * (curveBack[n] / curveRes[n]) # was -4 *
- growSpline(n, spl, numSplit, splitAngle[n], splitAngleV[n], splineList, handles, splineToBone,
- closeTip, kp, splitHeight, attractOut[n], stemsegL, lengthV[n], taperCrown, boneStep, rotate, rotateV)
+ growSpline(
+ n, spl, numSplit, splitAngle[n], splitAngleV[n], splineList,
+ handles, splineToBone, closeTip, kp, splitHeight, attractOut[n],
+ stemsegL, lengthV[n], taperCrown, boneStep, rotate, rotateV
+ )
# If pruning is enabled then we must to the check to see if the end of the spline is within the evelope
if prune:
@@ -1266,7 +1375,8 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
currentMax = currentScale
currentScale = 0.5 * (currentMax + currentMin)
break
- # If the scale is the original size and the point is inside then we need to make sure it won't be pruned or extended to the edge of the envelope
+ # If the scale is the original size and the point is inside then
+ # we need to make sure it won't be pruned or extended to the edge of the envelope
if insideBool and (currentScale != 1):
currentMin = currentScale
currentMax = oldMax
@@ -1274,13 +1384,14 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
if insideBool and ((currentMax - currentMin) == 1):
currentMin = 1
- # If the search will halt on the next iteration then we need to make sure we sprout child points to grow the next splines or leaves
+ # If the search will halt on the next iteration then we need
+ # to make sure we sprout child points to grow the next splines or leaves
if (((currentMax - currentMin) < 0.005) or not prune) or forceSprout:
if (n == 0) and (rMode != "original"):
tVals = findChildPoints2(splineList, st.children)
else:
tVals = findChildPoints(splineList, st.children)
- #print("debug tvals[%d] , splineList[%d], %s" % ( len(tVals), len(splineList), st.children))
+ # print("debug tvals[%d] , splineList[%d], %s" % ( len(tVals), len(splineList), st.children))
# If leaves is -ve then we need to make sure the only point which sprouts is the end of the spline
if not st.children:
tVals = [1.0]
@@ -1288,14 +1399,14 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
trimNum = int(baseSize * (len(tVals) + 1))
tVals = tVals[trimNum:]
- #grow branches in rings
+ # grow branches in rings
if (n == 0) and (nrings > 0):
- #tVals = [(floor(t * nrings)) / nrings for t in tVals[:-1]]
+ # tVals = [(floor(t * nrings)) / nrings for t in tVals[:-1]]
tVals = [(floor(t * nrings) / nrings) * uniform(.995, 1.005) for t in tVals[:-1]]
tVals.append(1)
tVals = [t for t in tVals if t > baseSize]
- #branch distribution
+ # branch distribution
if n == 0:
tVals = [((t - baseSize) / (1 - baseSize)) for t in tVals]
if branchDist < 1.0:
@@ -1307,7 +1418,7 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
# For all the splines, we interpolate them and add the new points to the list of child points
maxOffset = max([s.offsetLen + (len(s.spline.bezier_points) - 1) * s.segL for s in splineList])
for s in splineList:
- #print(str(n)+'level: ', s.segMax*s.segL)
+ # print(str(n)+'level: ', s.segMax*s.segL)
childP.extend(interpStem(s, tVals, s.segMax * s.segL, s.radS, maxOffset, baseSize))
# Force the splines to be deleted
@@ -1317,7 +1428,8 @@ def perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin, cu
startPrune = False
return ratio, splineToBone
-#calculate taper automaticly
+
+# calculate taper automaticly
def findtaper(length, taper, shape, shapeS, levels, customShape):
taperS = []
for i, t in enumerate(length):
@@ -1333,7 +1445,7 @@ def findtaper(length, taper, shape, shapeS, levels, customShape):
taperP = []
for i, t in enumerate(taperS):
pm = 1
- for x in range(i+1):
+ for x in range(i + 1):
pm *= taperS[x]
taperP.append(pm)
@@ -1357,32 +1469,32 @@ def findtaper(length, taper, shape, shapeS, levels, customShape):
def addTree(props):
global splitError
- #startTime = time.time()
+ # startTime = time.time()
# Set the seed for repeatable results
- seed(props.seed)#
+ seed(props.seed)
# Set all other variables
- levels = props.levels#
- length = props.length#
- lengthV = props.lengthV#
+ levels = props.levels
+ length = props.length
+ lengthV = props.lengthV
taperCrown = props.taperCrown
- branches = props.branches#
- curveRes = props.curveRes#
- curve = toRad(props.curve)#
- curveV = toRad(props.curveV)#
- curveBack = toRad(props.curveBack)#
- baseSplits = props.baseSplits#
- segSplits = props.segSplits#
+ branches = props.branches
+ curveRes = props.curveRes
+ curve = toRad(props.curve)
+ curveV = toRad(props.curveV)
+ curveBack = toRad(props.curveBack)
+ baseSplits = props.baseSplits
+ segSplits = props.segSplits
splitByLen = props.splitByLen
rMode = props.rMode
- splitAngle = toRad(props.splitAngle)#
- splitAngleV = toRad(props.splitAngleV)#
- scale = props.scale#
- scaleV = props.scaleV#
- attractUp = props.attractUp#
+ splitAngle = toRad(props.splitAngle)
+ splitAngleV = toRad(props.splitAngleV)
+ scale = props.scale
+ scaleV = props.scaleV
+ attractUp = props.attractUp
attractOut = props.attractOut
- shape = int(props.shape)#
- shapeS = int(props.shapeS)#
+ shape = int(props.shape)
+ shapeS = int(props.shapeS)
customShape = props.customShape
branchDist = props.branchDist
nrings = props.nrings
@@ -1395,38 +1507,38 @@ def addTree(props):
closeTip = props.closeTip
rootFlare = props.rootFlare
autoTaper = props.autoTaper
- taper = props.taper#
+ taper = props.taper
radiusTweak = props.radiusTweak
- ratioPower = props.ratioPower#
- downAngle = toRad(props.downAngle)#
- downAngleV = toRad(props.downAngleV)#
- rotate = toRad(props.rotate)#
- rotateV = toRad(props.rotateV)#
- scale0 = props.scale0#
- scaleV0 = props.scaleV0#
- prune = props.prune#
- pruneWidth = props.pruneWidth#
+ ratioPower = props.ratioPower
+ downAngle = toRad(props.downAngle)
+ downAngleV = toRad(props.downAngleV)
+ rotate = toRad(props.rotate)
+ rotateV = toRad(props.rotateV)
+ scale0 = props.scale0
+ scaleV0 = props.scaleV0
+ prune = props.prune
+ pruneWidth = props.pruneWidth
pruneBase = props.pruneBase
- pruneWidthPeak = props.pruneWidthPeak#
- prunePowerLow = props.prunePowerLow#
- prunePowerHigh = props.prunePowerHigh#
- pruneRatio = props.pruneRatio#
+ pruneWidthPeak = props.pruneWidthPeak
+ prunePowerLow = props.prunePowerLow
+ prunePowerHigh = props.prunePowerHigh
+ pruneRatio = props.pruneRatio
leafDownAngle = radians(props.leafDownAngle)
leafDownAngleV = radians(props.leafDownAngleV)
leafRotate = radians(props.leafRotate)
leafRotateV = radians(props.leafRotateV)
- leafScale = props.leafScale#
- leafScaleX = props.leafScaleX#
+ leafScale = props.leafScale
+ leafScaleX = props.leafScaleX
leafScaleT = props.leafScaleT
leafScaleV = props.leafScaleV
leafShape = props.leafShape
leafDupliObj = props.leafDupliObj
- bend = props.bend#
+ bend = props.bend
leafangle = props.leafangle
horzLeaves = props.horzLeaves
- leafDist = int(props.leafDist)#
- bevelRes = props.bevelRes#
- resU = props.resU#
+ leafDist = int(props.leafDist)
+ bevelRes = props.bevelRes
+ resU = props.resU
useArm = props.useArm
previewArm = props.previewArm
@@ -1435,8 +1547,8 @@ def addTree(props):
frameRate = props.frameRate
loopFrames = props.loopFrames
- #windSpeed = props.windSpeed
- #windGust = props.windGust
+ # windSpeed = props.windSpeed
+ # windGust = props.windGust
wind = props.wind
gust = props.gust
@@ -1456,11 +1568,11 @@ def addTree(props):
if not makeMesh:
boneStep = [1, 1, 1, 1]
- #taper
+ # taper
if autoTaper:
taper = findtaper(length, taper, shape, shapeS, levels, customShape)
- #pLevels = branches[0]
- #taper = findtaper(length, taper, shape, shapeS, pLevels, customShape)
+ # pLevels = branches[0]
+ # taper = findtaper(length, taper, shape, shapeS, pLevels, customShape)
leafObj = None
@@ -1488,7 +1600,7 @@ def addTree(props):
treeOb = bpy.data.objects.new('tree', cu)
bpy.context.scene.objects.link(treeOb)
-# treeOb.location=bpy.context.scene.cursor_location attractUp
+ # treeOb.location=bpy.context.scene.cursor_location attractUp
cu.dimensions = '3D'
cu.fill_mode = 'FULL'
@@ -1517,9 +1629,15 @@ def addTree(props):
for c in range(enNum):
newSpline.bezier_points.add()
newPoint = newSpline.bezier_points[-1]
- ratioVal = (c+1)/(enNum)
- zVal = scaleVal - scaleVal*(1-pruneBase)*ratioVal
- newPoint.co = Vector((scaleVal*pruneWidth*shapeRatio(9, ratioVal, pruneWidthPeak, prunePowerHigh, prunePowerLow), 0, zVal))
+ ratioVal = (c + 1) / (enNum)
+ zVal = scaleVal - scaleVal * (1 - pruneBase) * ratioVal
+ newPoint.co = Vector(
+ (
+ scaleVal * pruneWidth *
+ shapeRatio(9, ratioVal, pruneWidthPeak, prunePowerHigh, prunePowerLow),
+ 0, zVal
+ )
+ )
(newPoint.handle_right_type, newPoint.handle_left_type) = (enHandle, enHandle)
newSpline = enCu.splines.new('BEZIER')
newPoint = newSpline.bezier_points[-1]
@@ -1529,12 +1647,17 @@ def addTree(props):
for c in range(enNum):
newSpline.bezier_points.add()
newPoint = newSpline.bezier_points[-1]
- ratioVal = (c+1)/(enNum)
- zVal = scaleVal - scaleVal*(1-pruneBase)*ratioVal
- newPoint.co = Vector((0, scaleVal*pruneWidth*shapeRatio(9, ratioVal, pruneWidthPeak, prunePowerHigh, prunePowerLow), zVal))
+ ratioVal = (c + 1) / (enNum)
+ zVal = scaleVal - scaleVal * (1 - pruneBase) * ratioVal
+ newPoint.co = Vector(
+ (
+ 0, scaleVal * pruneWidth *
+ shapeRatio(9, ratioVal, pruneWidthPeak, prunePowerHigh, prunePowerLow),
+ zVal
+ )
+ )
(newPoint.handle_right_type, newPoint.handle_left_type) = (enHandle, enHandle)
-
childP = []
stemList = []
@@ -1547,16 +1670,18 @@ def addTree(props):
storeN = n
stemList = deque()
addstem = stemList.append
- # If n is used as an index to access parameters for the tree it must be at most 3 or it will reference outside the array index
+ # If n is used as an index to access parameters for the tree
+ # it must be at most 3 or it will reference outside the array index
n = min(3, n)
splitError = 0.0
- #closeTip only on last level
- closeTipp = all([(n == levels-1), closeTip])
+ # closeTip only on last level
+ closeTipp = all([(n == levels - 1), closeTip])
# If this is the first level of growth (the trunk) then we need some special work to begin the tree
if n == 0:
- kickstart_trunk(addstem, levels, leaves, branches, cu, curve, curveRes, curveV, attractUp, length, lengthV, ratio, ratioPower, resU,
+ kickstart_trunk(addstem, levels, leaves, branches, cu, curve, curveRes,
+ curveV, attractUp, length, lengthV, ratio, ratioPower, resU,
scale0, scaleV0, scaleVal, taper, minRadius, rootFlare)
# If this isn't the trunk then we may have multiple stem to intialise
else:
@@ -1567,20 +1692,22 @@ def addTree(props):
taper, shapeS, minRadius, radiusTweak, customShape, rMode, segSplits,
useOldDownAngle, useParentAngle, boneStep)
- #change base size for each level
+ # change base size for each level
if n > 0:
- baseSize *= baseSize_s #decrease at each level
+ baseSize *= baseSize_s # decrease at each level
if (n == levels - 1):
baseSize = 0
childP = []
# Now grow each of the stems in the list of those to be extended
for st in stemList:
- # When using pruning, we need to ensure that the random effects will be the same for each iteration to make sure the problem is linear.
+ # When using pruning, we need to ensure that the random effects
+ # will be the same for each iteration to make sure the problem is linear
randState = getstate()
startPrune = True
lengthTest = 0.0
- # Store all the original values for the stem to make sure we have access after it has been modified by pruning
+ # Store all the original values for the stem to make sure
+ # we have access after it has been modified by pruning
originalLength = st.segL
originalCurv = st.curv
originalCurvV = st.curvV
@@ -1595,16 +1722,20 @@ def addTree(props):
deleteSpline = False
orginalSplineToBone = copy.copy(splineToBone)
forceSprout = False
- # Now do the iterative pruning, this uses a binary search and halts once the difference between upper and lower bounds of the search are less than 0.005
- ratio, splineToBone = perform_pruning(baseSize, baseSplits, childP, cu, currentMax, currentMin,
- currentScale, curve, curveBack, curveRes, deleteSpline, forceSprout,
- handles, n, oldMax, orginalSplineToBone, originalCo, originalCurv,
- originalCurvV, originalHandleL, originalHandleR, originalLength,
- originalSeg, prune, prunePowerHigh, prunePowerLow, pruneRatio,
- pruneWidth, pruneBase, pruneWidthPeak, randState, ratio, scaleVal, segSplits,
- splineToBone, splitAngle, splitAngleV, st, startPrune,
- branchDist, length, splitByLen, closeTipp, nrings, splitBias, splitHeight, attractOut, rMode, lengthV,
- taperCrown, boneStep, rotate, rotateV)
+ # Now do the iterative pruning, this uses a binary search and halts once the difference
+ # between upper and lower bounds of the search are less than 0.005
+ ratio, splineToBone = perform_pruning(
+ baseSize, baseSplits, childP, cu, currentMax, currentMin,
+ currentScale, curve, curveBack, curveRes, deleteSpline, forceSprout,
+ handles, n, oldMax, orginalSplineToBone, originalCo, originalCurv,
+ originalCurvV, originalHandleL, originalHandleR, originalLength,
+ originalSeg, prune, prunePowerHigh, prunePowerLow, pruneRatio,
+ pruneWidth, pruneBase, pruneWidthPeak, randState, ratio, scaleVal,
+ segSplits, splineToBone, splitAngle, splitAngleV, st, startPrune,
+ branchDist, length, splitByLen, closeTipp, nrings, splitBias,
+ splitHeight, attractOut, rMode, lengthV, taperCrown, boneStep,
+ rotate, rotateV
+ )
levelCount.append(len(cu.splines))
@@ -1613,43 +1744,53 @@ def addTree(props):
leafFaces = []
leafNormals = []
- leafMesh = None # in case we aren't creating leaves, we'll still have the variable
+ leafMesh = None # in case we aren't creating leaves, we'll still have the variable
leafP = []
if leaves:
oldRot = 0.0
- n = min(3, n+1)
+ n = min(3, n + 1)
# For each of the child points we add leaves
for cp in childP:
# If the special flag is set then we need to add several leaves at the same location
if leaves < 0:
oldRot = -leafRotate / 2
for g in range(abs(leaves)):
- (vertTemp, faceTemp, normal, oldRot) = genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, cp.co, cp.quat, cp.offset,
- len(leafVerts), leafDownAngle, leafDownAngleV, leafRotate, leafRotateV,
- oldRot, bend, leaves, leafShape, leafangle, horzLeaves)
+ (vertTemp, faceTemp, normal, oldRot) = genLeafMesh(
+ leafScale, leafScaleX, leafScaleT,
+ leafScaleV, cp.co, cp.quat, cp.offset,
+ len(leafVerts), leafDownAngle, leafDownAngleV,
+ leafRotate, leafRotateV,
+ oldRot, bend, leaves, leafShape,
+ leafangle, horzLeaves
+ )
leafVerts.extend(vertTemp)
leafFaces.extend(faceTemp)
leafNormals.extend(normal)
leafP.append(cp)
- # Otherwise just add the leaves like splines.
+ # Otherwise just add the leaves like splines
else:
- (vertTemp, faceTemp, normal, oldRot) = genLeafMesh(leafScale, leafScaleX, leafScaleT, leafScaleV, cp.co, cp.quat, cp.offset,
- len(leafVerts), leafDownAngle, leafDownAngleV, leafRotate, leafRotateV,
- oldRot, bend, leaves, leafShape, leafangle, horzLeaves)
+ (vertTemp, faceTemp, normal, oldRot) = genLeafMesh(
+ leafScale, leafScaleX, leafScaleT, leafScaleV,
+ cp.co, cp.quat, cp.offset, len(leafVerts),
+ leafDownAngle, leafDownAngleV, leafRotate,
+ leafRotateV, oldRot, bend, leaves, leafShape,
+ leafangle, horzLeaves
+ )
leafVerts.extend(vertTemp)
leafFaces.extend(faceTemp)
leafNormals.extend(normal)
leafP.append(cp)
- # Create the leaf mesh and object, add geometry using from_pydata, edges are currently added by validating the mesh which isn't great
+ # Create the leaf mesh and object, add geometry using from_pydata,
+ # edges are currently added by validating the mesh which isn't great
leafMesh = bpy.data.meshes.new('leaves')
leafObj = bpy.data.objects.new('leaves', leafMesh)
bpy.context.scene.objects.link(leafObj)
leafObj.parent = treeOb
leafMesh.from_pydata(leafVerts, (), leafFaces)
- #set vertex normals for dupliVerts
+ # set vertex normals for dupliVerts
if leafShape == 'dVert':
leafMesh.vertices.foreach_set('normal', leafNormals)
@@ -1659,18 +1800,20 @@ def addTree(props):
leafObj.use_dupli_faces_scale = True
leafObj.dupli_faces_scale = 10.0
try:
- bpy.data.objects[leafDupliObj].parent = leafObj
+ if leafDupliObj not in "NONE":
+ bpy.data.objects[leafDupliObj].parent = leafObj
except KeyError:
pass
elif leafShape == 'dVert':
leafObj.dupli_type = "VERTS"
leafObj.use_dupli_vertices_rotation = True
try:
- bpy.data.objects[leafDupliObj].parent = leafObj
+ if leafDupliObj not in "NONE":
+ bpy.data.objects[leafDupliObj].parent = leafObj
except KeyError:
pass
- #add leaf UVs
+ # add leaf UVs
if leafShape == 'rect':
leafMesh.uv_textures.new("leafUV")
uvlayer = leafMesh.uv_layers.active.data
@@ -1679,10 +1822,10 @@ def addTree(props):
u2 = 1 - u1
for i in range(0, len(leafFaces)):
- uvlayer[i*4 + 0].uv = Vector((u2, 0))
- uvlayer[i*4 + 1].uv = Vector((u2, 1))
- uvlayer[i*4 + 2].uv = Vector((u1, 1))
- uvlayer[i*4 + 3].uv = Vector((u1, 0))
+ uvlayer[i * 4 + 0].uv = Vector((u2, 0))
+ uvlayer[i * 4 + 1].uv = Vector((u2, 1))
+ uvlayer[i * 4 + 2].uv = Vector((u1, 1))
+ uvlayer[i * 4 + 3].uv = Vector((u1, 0))
elif leafShape == 'hex':
leafMesh.uv_textures.new("leafUV")
@@ -1692,15 +1835,15 @@ def addTree(props):
u2 = 1 - u1
for i in range(0, int(len(leafFaces) / 2)):
- uvlayer[i*8 + 0].uv = Vector((.5, 0))
- uvlayer[i*8 + 1].uv = Vector((u1, 1/3))
- uvlayer[i*8 + 2].uv = Vector((u1, 2/3))
- uvlayer[i*8 + 3].uv = Vector((.5, 1))
+ uvlayer[i * 8 + 0].uv = Vector((.5, 0))
+ uvlayer[i * 8 + 1].uv = Vector((u1, 1 / 3))
+ uvlayer[i * 8 + 2].uv = Vector((u1, 2 / 3))
+ uvlayer[i * 8 + 3].uv = Vector((.5, 1))
- uvlayer[i*8 + 4].uv = Vector((.5, 0))
- uvlayer[i*8 + 5].uv = Vector((.5, 1))
- uvlayer[i*8 + 6].uv = Vector((u2, 2/3))
- uvlayer[i*8 + 7].uv = Vector((u2, 1/3))
+ uvlayer[i * 8 + 4].uv = Vector((.5, 0))
+ uvlayer[i * 8 + 5].uv = Vector((.5, 1))
+ uvlayer[i * 8 + 6].uv = Vector((u2, 2 / 3))
+ uvlayer[i * 8 + 7].uv = Vector((u2, 1 / 3))
leafMesh.validate()
@@ -1719,13 +1862,15 @@ def addTree(props):
# If we need an armature we add it
if useArm:
# Create the armature and objects
- create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSize, leaves, levelCount, splineToBone,
- treeOb, wind, gust, gustF, af1, af2, af3, leafAnim, loopFrames, previewArm, armLevels, makeMesh, boneStep)
-
- #print(time.time()-startTime)
+ create_armature(
+ armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSize,
+ leaves, levelCount, splineToBone, treeOb, wind, gust, gustF, af1,
+ af2, af3, leafAnim, loopFrames, previewArm, armLevels, makeMesh, boneStep
+ )
+ # print(time.time()-startTime)
- #mesh branches
+ # mesh branches
if makeMesh:
t1 = time.time()
@@ -1743,7 +1888,7 @@ def addTree(props):
for i, curve in enumerate(cu.splines):
points = curve.bezier_points
- #find branching level
+ # find branching level
level = 0
for l, c in enumerate(levelCount):
if i < c:
@@ -1756,46 +1901,46 @@ def addTree(props):
p1 = points[0]
- #add extra vertex for splits
+ # add extra vertex for splits
if issplit[i]:
pb = int(splineToBone[i][4:-4])
- pn = splitPidx[i] #int(splineToBone[i][-3:])
+ pn = splitPidx[i] # int(splineToBone[i][-3:])
p_1 = cu.splines[pb].bezier_points[pn]
- p_2 = cu.splines[pb].bezier_points[pn+1]
- p = evalBez(p_1.co, p_1.handle_right, p_2.handle_left, p_2.co, 1 - 1/(resU + 1))
+ p_2 = cu.splines[pb].bezier_points[pn + 1]
+ p = evalBez(p_1.co, p_1.handle_right, p_2.handle_left, p_2.co, 1 - 1 / (resU + 1))
treeVerts.append(p)
root_vert.append(False)
vert_radius.append((p1.radius * .75, p1.radius * .75))
- treeEdges.append([vindex,vindex+1])
+ treeEdges.append([vindex, vindex + 1])
vindex += 1
if isend[i]:
parent = lastVerts[int(splineToBone[i][4:-4])]
vindex -= 1
else:
- #add first point
+ # add first point
treeVerts.append(p1.co)
root_vert.append(True)
vert_radius.append((p1.radius, p1.radius))
-
-# #add extra vertex for splits
-# if issplit[i]:
-# p2 = points[1]
-# p = evalBez(p1.co, p1.handle_right, p2.handle_left, p2.co, .001)
-# treeVerts.append(p)
-# root_vert.append(False)
-# vert_radius.append((p1.radius, p1.radius)) #(p1.radius * .95, p1.radius * .95)
-# treeEdges.append([vindex,vindex+1])
-# vindex += 1
-
- #dont make vertex group if above armLevels
+ """
+ # add extra vertex for splits
+ if issplit[i]:
+ p2 = points[1]
+ p = evalBez(p1.co, p1.handle_right, p2.handle_left, p2.co, .001)
+ treeVerts.append(p)
+ root_vert.append(False)
+ vert_radius.append((p1.radius, p1.radius)) #(p1.radius * .95, p1.radius * .95)
+ treeEdges.append([vindex,vindex+1])
+ vindex += 1
+ """
+ # dont make vertex group if above armLevels
if (i >= levelCount[armLevels]):
idx = i
groupName = splineToBone[idx]
g = True
while groupName not in vertexGroups:
- #find parent bone of parent bone
+ # find parent bone of parent bone
b = splineToBone[idx]
idx = int(b[4:-4])
groupName = splineToBone[idx]
@@ -1816,7 +1961,7 @@ def addTree(props):
else:
vertexGroups[splineToBone[i]].append(vindex - 1)
- for f in range(1, resU+1):
+ for f in range(1, resU + 1):
pos = f / resU
p = evalBez(p1.co, p1.handle_right, p2.handle_left, p2.co, pos)
radius = p1.radius + (p2.radius - p1.radius) * pos
@@ -1829,7 +1974,7 @@ def addTree(props):
edge = [parent, n * resU + f + vindex]
else:
edge = [n * resU + f + vindex - 1, n * resU + f + vindex]
- #add vert to group
+ # add vert to group
vertexGroups[groupName].append(n * resU + f + vindex - 1)
treeEdges.append(edge)
@@ -1837,7 +1982,7 @@ def addTree(props):
p1 = p2
- lastVerts.append(len(treeVerts)-1)
+ lastVerts.append(len(treeVerts) - 1)
treeMesh.from_pydata(treeVerts, treeEdges, ())
@@ -1845,7 +1990,7 @@ def addTree(props):
treeObj.vertex_groups.new(group)
treeObj.vertex_groups[group].add(vertexGroups[group], 1.0, 'ADD')
- #add armature
+ # add armature
if useArm:
armMod = treeObj.modifiers.new('windSway', 'ARMATURE')
if previewArm:
@@ -1856,7 +2001,7 @@ def addTree(props):
armMod.use_vertex_groups = True
treeObj.parent = bpy.data.objects['treeArm']
- #add skin modifier and set data
+ # add skin modifier and set data
skinMod = treeObj.modifiers.new('Skin', 'SKIN')
skinMod.use_smooth_shade = True
if previewArm: