Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
blender-addons
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
blender
blender-addons
Commits
09e37c1f
Commit
09e37c1f
authored
13 years ago
by
Andrew Hale
Browse files
Options
Downloads
Patches
Plain Diff
Moved to Trunk
[[Split portion of a mixed commit.]]
parent
cad685e2
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
add_curve_ivygen.py
+687
-0
687 additions, 0 deletions
add_curve_ivygen.py
with
687 additions
and
0 deletions
add_curve_ivygen.py
0 → 100644
+
687
−
0
View file @
09e37c1f
# ##### 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
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# 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 #####
# <pep8-80 compliant>
bl_info
=
{
"
name
"
:
"
IvyGen
"
,
"
author
"
:
"
testscreenings, PKHG, TrumanBlending
"
,
"
version
"
:
(
0
,
1
,
0
),
"
blender
"
:
(
2
,
5
,
8
),
"
api
"
:
38479
,
"
location
"
:
"
View3D > Add > Curve
"
,
"
description
"
:
"
Adds generated ivy to a mesh object starting at the 3D
"
\
"
cursor.
"
,
"
warning
"
:
""
,
"
wiki_url
"
:
"
http://wiki.blender.org/index.php/Extensions:2.5/Py/
"
\
"
Scripts/Curve/Ivy_Gen
"
,
"
tracker_url
"
:
"
http://projects.blender.org/tracker/index.php?
"
\
"
func=detail&aid=27234
"
,
"
category
"
:
"
Add Curve
"
}
import
bpy
from
bpy.props
import
FloatProperty
,
IntProperty
,
BoolProperty
from
mathutils
import
Vector
,
Matrix
from
collections
import
deque
from
math
import
pow
,
cos
,
pi
,
atan2
from
random
import
random
as
rand_val
,
seed
as
rand_seed
import
time
def
createIvyGeometry
(
IVY
,
growLeaves
):
'''
Create the curve geometry for IVY
'''
# Compute the local size and the gauss weight filter
#local_ivyBranchSize = IVY.ivyBranchSize # * radius * IVY.ivySize
gaussWeight
=
[
1.0
,
2.0
,
4.0
,
7.0
,
9.0
,
10.0
,
9.0
,
7.0
,
4.0
,
2.0
,
1.0
]
# Create a new curve and intialise it
curve
=
bpy
.
data
.
curves
.
new
(
"
IVY
"
,
type
=
'
CURVE
'
)
curve
.
dimensions
=
'
3D
'
curve
.
bevel_depth
=
1
curve
.
use_fill_front
=
curve
.
use_fill_back
=
False
if
growLeaves
:
# Create the ivy leaves
# Order location of the vertices
signList
=
[(
-
1
,
1
),
(
1
,
1
),
(
1
,
-
1
),
(
-
1
,
-
1
)]
# Get the local size
#local_ivyLeafSize = IVY.ivyLeafSize # * radius * IVY.ivySize
# Initialise the vertex and face lists
vertList
=
deque
()
# Store the methods for faster calling
addV
=
vertList
.
extend
rotMat
=
Matrix
.
Rotation
# Loop over all roots to generate its nodes
for
root
in
IVY
.
ivyRoots
:
# Only grow if more than one node
numNodes
=
len
(
root
.
ivyNodes
)
if
numNodes
>
1
:
# Calculate the local radius
local_ivyBranchRadius
=
1
/
(
root
.
parents
+
1
)
+
1
prevIvyLength
=
1
/
root
.
ivyNodes
[
-
1
].
length
splineVerts
=
[
ax
for
n
in
root
.
ivyNodes
for
ax
in
n
.
pos
.
to_4d
()]
radiusConstant
=
local_ivyBranchRadius
*
IVY
.
ivyBranchSize
splineRadii
=
[
radiusConstant
*
(
1.3
-
n
.
length
*
prevIvyLength
)
for
n
in
root
.
ivyNodes
]
# Add the poly curve and set coords and radii
newSpline
=
curve
.
splines
.
new
(
type
=
'
POLY
'
)
newSpline
.
points
.
add
(
len
(
splineVerts
)
//
4
-
1
)
newSpline
.
points
.
foreach_set
(
'
co
'
,
splineVerts
)
newSpline
.
points
.
foreach_set
(
'
radius
'
,
splineRadii
)
# Loop over all nodes in the root
for
i
,
n
in
enumerate
(
root
.
ivyNodes
):
for
k
in
range
(
len
(
gaussWeight
)):
idx
=
max
(
0
,
min
(
i
+
k
-
5
,
numNodes
-
1
))
n
.
smoothAdhesionVector
+=
(
gaussWeight
[
k
]
*
root
.
ivyNodes
[
idx
].
adhesionVector
)
n
.
smoothAdhesionVector
/=
56.0
n
.
adhesionLength
=
n
.
smoothAdhesionVector
.
length
n
.
smoothAdhesionVector
.
normalize
()
if
growLeaves
and
(
i
<
numNodes
-
1
):
node
=
root
.
ivyNodes
[
i
]
nodeNext
=
root
.
ivyNodes
[
i
+
1
]
# Find the weight and normalise the smooth adhesion vector
weight
=
pow
(
node
.
length
*
prevIvyLength
,
0.7
)
# Calculate the ground ivy and the new weight
groundIvy
=
max
(
0.0
,
-
node
.
smoothAdhesionVector
.
z
)
weight
+=
groundIvy
*
pow
(
1
-
node
.
length
*
prevIvyLength
,
2
)
# Find the alignment weight
alignmentWeight
=
node
.
adhesionLength
# Calculate the needed angles
phi
=
atan2
(
node
.
smoothAdhesionVector
.
y
,
node
.
smoothAdhesionVector
.
x
)
-
pi
/
2
theta
=
(
0.5
*
node
.
smoothAdhesionVector
.
angle
(
Vector
((
0
,
0
,
-
1
)),
0
))
# Find the size weight
sizeWeight
=
1.5
-
(
cos
(
2
*
pi
*
weight
)
*
0.5
+
0.5
)
# Randomise the angles
phi
+=
(
rand_val
()
-
0.5
)
*
(
1.3
-
alignmentWeight
)
theta
+=
(
rand_val
()
-
0.5
)
*
(
1.1
-
alignmentWeight
)
# Calculate the leaf size an append the face to the list
leafSize
=
IVY
.
ivyLeafSize
*
sizeWeight
for
j
in
range
(
10
):
# Generate the probability
probability
=
rand_val
()
# If we need to grow a leaf, do so
if
(
probability
*
weight
)
>
IVY
.
leafProbability
:
# Generate the random vector
randomVector
=
Vector
((
rand_val
()
-
0.5
,
rand_val
()
-
0.5
,
rand_val
()
-
0.5
))
# Find the leaf center
center
=
node
.
pos
.
lerp
(
nodeNext
.
pos
,
j
/
10
)
+
\
IVY
.
ivyLeafSize
*
randomVector
# For each of the verts, rotate/scale and append
basisVecX
=
Vector
((
1
,
0
,
0
))
basisVecY
=
Vector
((
0
,
1
,
0
))
horiRot
=
rotMat
(
theta
,
3
,
'
X
'
)
vertRot
=
rotMat
(
phi
,
3
,
'
Z
'
)
basisVecX
.
rotate
(
horiRot
)
basisVecY
.
rotate
(
horiRot
)
basisVecX
.
rotate
(
vertRot
)
basisVecY
.
rotate
(
vertRot
)
basisVecX
*=
leafSize
basisVecY
*=
leafSize
addV
([
k1
*
basisVecX
+
k2
*
basisVecY
+
center
for
k1
,
k2
in
signList
])
# Add the object and link to scene
newCurve
=
bpy
.
data
.
objects
.
new
(
"
IVY_Curve
"
,
curve
)
bpy
.
context
.
scene
.
objects
.
link
(
newCurve
)
if
growLeaves
:
faceList
=
[[
4
*
i
+
l
for
l
in
range
(
4
)]
for
i
in
range
(
len
(
vertList
)
//
4
)]
# Generate the new leaf mesh and link
me
=
bpy
.
data
.
meshes
.
new
(
'
IvyLeaf
'
)
me
.
from_pydata
(
vertList
,
[],
faceList
)
me
.
update
(
calc_edges
=
True
)
ob
=
bpy
.
data
.
objects
.
new
(
'
IvyLeaf
'
,
me
)
bpy
.
context
.
scene
.
objects
.
link
(
ob
)
tex
=
me
.
uv_textures
.
new
(
"
Leaves
"
)
# Set the uv texture coords
for
d
in
tex
.
data
:
uv1
,
uv2
,
uv3
,
uv4
=
signList
ob
.
parent
=
newCurve
def
computeBoundingSphere
(
ob
):
# Get the mesh data
me
=
ob
.
data
# Intialise the center
center
=
Vector
((
0
,
0
,
0
))
# Add all vertex coords
for
v
in
me
.
vertices
:
center
+=
v
.
co
# Average over all verts
center
/=
len
(
me
.
vertices
)
# Create the iterator and find its max
length_iter
=
((
center
-
v
.
co
).
length
for
v
in
me
.
vertices
)
radius
=
max
(
length_iter
)
return
radius
class
IvyNode
:
"""
The basic class used for each point on the ivy which is grown.
"""
__slots__
=
(
'
pos
'
,
'
primaryDir
'
,
'
adhesionVector
'
,
'
adhesionLength
'
,
'
smoothAdhesionVector
'
,
'
length
'
,
'
floatingLength
'
,
'
climb
'
)
def
__init__
(
self
):
self
.
pos
=
Vector
((
0
,
0
,
0
))
self
.
primaryDir
=
Vector
((
0
,
0
,
1
))
self
.
adhesionVector
=
Vector
((
0
,
0
,
0
))
self
.
smoothAdhesionVector
=
Vector
((
0
,
0
,
0
))
self
.
length
=
0.0001
self
.
floatingLength
=
0.0
self
.
climb
=
True
class
IvyRoot
:
"""
The class used to hold all ivy nodes growing from this root point.
"""
__slots__
=
(
'
ivyNodes
'
,
'
alive
'
,
'
parents
'
)
def
__init__
(
self
):
self
.
ivyNodes
=
deque
()
self
.
alive
=
True
self
.
parents
=
0
class
Ivy
:
"""
The class holding all parameters and ivy roots.
"""
__slots__
=
(
'
ivyRoots
'
,
'
primaryWeight
'
,
'
randomWeight
'
,
'
gravityWeight
'
,
'
adhesionWeight
'
,
'
branchingProbability
'
,
'
leafProbability
'
,
'
ivySize
'
,
'
ivyLeafSize
'
,
'
ivyBranchSize
'
,
'
maxFloatLength
'
,
'
maxAdhesionDistance
'
,
'
maxLength
'
)
def
__init__
(
self
,
primaryWeight
=
0.5
,
randomWeight
=
0.2
,
gravityWeight
=
1.0
,
adhesionWeight
=
0.1
,
branchingProbability
=
0.05
,
leafProbability
=
0.35
,
ivySize
=
0.02
,
ivyLeafSize
=
0.02
,
ivyBranchSize
=
0.001
,
maxFloatLength
=
0.5
,
maxAdhesionDistance
=
1.0
):
self
.
ivyRoots
=
deque
()
self
.
primaryWeight
=
primaryWeight
self
.
randomWeight
=
randomWeight
self
.
gravityWeight
=
gravityWeight
self
.
adhesionWeight
=
adhesionWeight
self
.
branchingProbability
=
1
-
branchingProbability
self
.
leafProbability
=
1
-
leafProbability
self
.
ivySize
=
ivySize
self
.
ivyLeafSize
=
ivyLeafSize
self
.
ivyBranchSize
=
ivyBranchSize
self
.
maxFloatLength
=
maxFloatLength
self
.
maxAdhesionDistance
=
maxAdhesionDistance
self
.
maxLength
=
0.0
# Normalise all the weights only on intialisation
sum
=
self
.
primaryWeight
+
self
.
randomWeight
+
self
.
adhesionWeight
self
.
primaryWeight
/=
sum
self
.
randomWeight
/=
sum
self
.
adhesionWeight
/=
sum
def
seed
(
self
,
seedPos
):
# Seed the Ivy by making a new root and first node
tmpRoot
=
IvyRoot
()
tmpIvy
=
IvyNode
()
tmpIvy
.
pos
=
seedPos
tmpRoot
.
ivyNodes
.
append
(
tmpIvy
)
self
.
ivyRoots
.
append
(
tmpRoot
)
def
grow
(
self
,
ob
):
# Determine the local sizes
#local_ivySize = self.ivySize # * radius
#local_maxFloatLength = self.maxFloatLength # * radius
#local_maxAdhesionDistance = self.maxAdhesionDistance # * radius
for
root
in
self
.
ivyRoots
:
# Make sure the root is alive, if not, skip
if
not
root
.
alive
:
continue
# Get the last node in the current root
prevIvy
=
root
.
ivyNodes
[
-
1
]
# If the node is floating for too long, kill the root
if
prevIvy
.
floatingLength
>
self
.
maxFloatLength
:
root
.
alive
=
False
# Set the primary direction from the last node
primaryVector
=
prevIvy
.
primaryDir
# Make the random vector and normalise
randomVector
=
Vector
((
rand_val
()
-
0.5
,
rand_val
()
-
0.5
,
rand_val
()
-
0.5
))
+
Vector
((
0
,
0
,
0.2
))
randomVector
.
normalize
()
# Calculate the adhesion vector
adhesionVector
=
adhesion
(
prevIvy
.
pos
,
ob
,
self
.
maxAdhesionDistance
)
# Calculate the growing vector
growVector
=
self
.
ivySize
*
(
primaryVector
*
self
.
primaryWeight
+
randomVector
*
self
.
randomWeight
+
adhesionVector
*
self
.
adhesionWeight
)
# Find the gravity vector
gravityVector
=
(
self
.
ivySize
*
self
.
gravityWeight
*
Vector
((
0
,
0
,
-
1
)))
gravityVector
*=
pow
(
prevIvy
.
floatingLength
/
self
.
maxFloatLength
,
0.7
)
# Determine the new position vector
newPos
=
prevIvy
.
pos
+
growVector
+
gravityVector
# Check for collisions with the object
climbing
=
collision
(
ob
,
prevIvy
.
pos
,
newPos
)
# Update the growing vector for any collisions
growVector
=
newPos
-
prevIvy
.
pos
-
gravityVector
growVector
.
normalize
()
# Create a new IvyNode and set its properties
tmpNode
=
IvyNode
()
tmpNode
.
climb
=
climbing
tmpNode
.
pos
=
newPos
tmpNode
.
primaryDir
=
prevIvy
.
primaryDir
.
lerp
(
growVector
,
0.5
)
tmpNode
.
primaryDir
.
normalize
()
tmpNode
.
adhesionVector
=
adhesionVector
tmpNode
.
length
=
prevIvy
.
length
+
(
newPos
-
prevIvy
.
pos
).
length
if
tmpNode
.
length
>
self
.
maxLength
:
self
.
maxLength
=
tmpNode
.
length
# If the node isn't climbing, update it's floating length
# Otherwise set it to 0
if
not
climbing
:
tmpNode
.
floatingLength
=
prevIvy
.
floatingLength
+
(
newPos
-
prevIvy
.
pos
).
length
else
:
tmpNode
.
floatingLength
=
0.0
root
.
ivyNodes
.
append
(
tmpNode
)
# Loop through all roots to check if a new root is generated
for
root
in
self
.
ivyRoots
:
# Check the root is alive and isn't at high level of recursion
if
(
root
.
parents
>
3
)
or
(
not
root
.
alive
):
continue
# Check to make sure there's more than 1 node
if
len
(
root
.
ivyNodes
)
>
1
:
# Loop through all nodes in root to check if new root is grown
for
node
in
root
.
ivyNodes
:
# Set the last node of the root and find the weighting
prevIvy
=
root
.
ivyNodes
[
-
1
]
weight
=
1.0
-
(
cos
(
2.0
*
pi
*
node
.
length
/
prevIvy
.
length
)
*
0.5
+
0.5
)
probability
=
rand_val
()
# Check if a new root is grown and if so, set its values
if
(
probability
*
weight
>
self
.
branchingProbability
):
tmpNode
=
IvyNode
()
tmpNode
.
pos
=
node
.
pos
tmpNode
.
floatingLength
=
node
.
floatingLength
tmpRoot
=
IvyRoot
()
tmpRoot
.
parents
=
root
.
parents
+
1
tmpRoot
.
ivyNodes
.
append
(
tmpNode
)
self
.
ivyRoots
.
append
(
tmpRoot
)
return
def
adhesion
(
loc
,
ob
,
max_l
):
# Get transfor vector and transformed loc
tran_mat
=
ob
.
matrix_world
.
inverted
()
tran_loc
=
tran_mat
*
loc
# Compute the adhesion vector by finding the nearest point
nearest_result
=
ob
.
closest_point_on_mesh
(
tran_loc
,
max_l
)
adhesion_vector
=
Vector
((
0
,
0
,
0
))
if
nearest_result
[
2
]
!=
-
1
:
# Compute the distance to the nearest point
adhesion_vector
=
ob
.
matrix_world
*
nearest_result
[
0
]
-
loc
distance
=
adhesion_vector
.
length
# If it's less than the maximum allowed and not 0, continue
if
distance
:
# Compute the direction vector between the closest point and loc
adhesion_vector
.
normalize
()
adhesion_vector
*=
1.0
-
distance
/
max_l
#adhesion_vector *= getFaceWeight(ob.data, nearest_result[2])
return
adhesion_vector
def
collision
(
ob
,
pos
,
new_pos
):
# Check for collision with the object
climbing
=
False
# Transform vecs
tran_mat
=
ob
.
matrix_world
.
inverted
()
tran_pos
=
tran_mat
*
pos
tran_new_pos
=
tran_mat
*
new_pos
ray_result
=
ob
.
ray_cast
(
tran_pos
,
tran_new_pos
)
# If there's a collision we need to check it
if
ray_result
[
2
]
!=
-
1
:
# Check whether the collision is going into the object
if
(
tran_new_pos
-
tran_pos
).
dot
(
ray_result
[
1
])
<
0.0
:
# Find projection of the piont onto the plane
p0
=
tran_new_pos
-
(
tran_new_pos
-
ray_result
[
0
]).
project
(
ray_result
[
1
])
# Reflect in the plane
tran_new_pos
+=
2
*
(
p0
-
tran_new_pos
)
new_pos
*=
0
new_pos
+=
ob
.
matrix_world
*
tran_new_pos
climbing
=
True
return
climbing
class
IvyGen
(
bpy
.
types
.
Operator
):
bl_idname
=
"
curve.ivy_gen
"
bl_label
=
"
IvyGen
"
bl_options
=
{
'
REGISTER
'
,
'
UNDO
'
}
maxIvyLength
=
FloatProperty
(
name
=
"
Max Ivy Length
"
,
description
=
"
Maximum ivy length in Blender Units.
"
,
default
=
1.0
,
min
=
0.0
,
soft_max
=
3.0
,
subtype
=
'
DISTANCE
'
,
unit
=
'
LENGTH
'
)
primaryWeight
=
FloatProperty
(
name
=
"
Primary Weight
"
,
description
=
"
Weighting given to the current direction.
"
,
default
=
0.5
,
min
=
0.0
,
soft_max
=
1.0
)
randomWeight
=
FloatProperty
(
name
=
"
Random Weight
"
,
description
=
"
Weighting given to the random direction.
"
,
default
=
0.2
,
min
=
0.0
,
soft_max
=
1.0
)
gravityWeight
=
FloatProperty
(
name
=
"
Gravity Weight
"
,
description
=
"
Weighting given to the gravity direction.
"
,
default
=
1.0
,
min
=
0.0
,
soft_max
=
1.0
)
adhesionWeight
=
FloatProperty
(
name
=
"
Adhesion Weight
"
,
description
=
"
Weighting given to the adhesion direction.
"
,
default
=
0.1
,
min
=
0.0
,
soft_max
=
1.0
)
branchingProbability
=
FloatProperty
(
name
=
"
Branching Probability
"
,
description
=
"
Probability of a new branch forming.
"
,
default
=
0.05
,
min
=
0.0
,
soft_max
=
1.0
)
leafProbability
=
FloatProperty
(
name
=
"
Leaf Probability
"
,
description
=
"
Probability of a leaf forming.
"
,
default
=
0.35
,
min
=
0.0
,
soft_max
=
1.0
)
ivySize
=
FloatProperty
(
name
=
"
Ivy Size
"
,
description
=
"
The length of an ivy segment in Blender
"
\
"
Units.
"
,
default
=
0.02
,
min
=
0.0
,
soft_max
=
1.0
,
precision
=
3
)
ivyLeafSize
=
FloatProperty
(
name
=
"
Ivy Leaf Size
"
,
description
=
"
The size of the ivy leaves
"
,
default
=
0.02
,
min
=
0.0
,
soft_max
=
0.5
,
precision
=
3
)
ivyBranchSize
=
FloatProperty
(
name
=
"
Ivy Branch Size
"
,
description
=
"
The size of the ivy branches
"
,
default
=
0.001
,
min
=
0.0
,
soft_max
=
0.1
,
precision
=
4
)
maxFloatLength
=
FloatProperty
(
name
=
"
Max Float Length
"
,
description
=
"
The maximum distance that a branch
"
\
"
can live while floating.
"
,
default
=
0.5
,
min
=
0.0
,
soft_max
=
1.0
)
maxAdhesionDistance
=
FloatProperty
(
name
=
"
Max Adhesion Length
"
,
description
=
"
The maximum distance that a branch
"
\
"
will feel the effects of adhesion.
"
,
default
=
1.0
,
min
=
0.0
,
soft_max
=
2.0
,
precision
=
2
)
randomSeed
=
FloatProperty
(
name
=
"
Random Seed
"
,
description
=
"
The seed governing random generation.
"
,
default
=
0
,
min
=
0.0
,
soft_max
=
10
)
maxTime
=
FloatProperty
(
name
=
"
Maximum Time
"
,
description
=
"
The maximum time to run the generation for
"
\
"
in seconds generation (0.0 = Disabled)
"
,
default
=
0.0
,
min
=
0.0
,
soft_max
=
10
)
growLeaves
=
BoolProperty
(
name
=
"
Grow Leaves
"
,
description
=
"
Grow leaves or not.
"
,
default
=
True
)
updateIvy
=
BoolProperty
(
name
=
"
Update Ivy
"
,
default
=
False
)
@classmethod
def
poll
(
self
,
context
):
# Check if there's an object and whether it's a mesh
ob
=
context
.
active_object
if
(
ob
is
not
None
)
and
\
(
ob
.
type
==
'
MESH
'
)
and
\
(
context
.
mode
==
'
OBJECT
'
):
return
True
return
False
def
execute
(
self
,
context
):
if
self
.
updateIvy
:
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
EDIT
'
,
toggle
=
False
)
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
OBJECT
'
,
toggle
=
False
)
# Get the selected object
ob
=
context
.
active_object
# Compute bounding sphere radius
#radius = computeBoundingSphere(ob) # Not needed anymore
# Get the seeding point
seedPoint
=
context
.
scene
.
cursor_location
# Fix the random seed
rand_seed
(
int
(
self
.
randomSeed
))
# Make the new ivy
IVY
=
Ivy
(
**
self
.
as_keywords
(
ignore
=
(
'
randomSeed
'
,
'
growLeaves
'
,
'
maxIvyLength
'
,
'
maxTime
'
,
'
updateIvy
'
)))
# Generate first root and node
IVY
.
seed
(
seedPoint
)
checkAlive
=
True
checkTime
=
False
maxLength
=
self
.
maxIvyLength
# * radius
# If we need to check time set the flag
if
self
.
maxTime
!=
0.0
:
checkTime
=
True
t
=
time
.
time
()
startPercent
=
0.0
checkAliveIter
=
[
True
,
]
# Grow until 200 roots is reached or backup counter exceeds limit
while
any
(
checkAliveIter
)
and
\
(
IVY
.
maxLength
<
maxLength
)
and
\
(
not
checkTime
or
(
time
.
time
()
-
t
<
self
.
maxTime
)):
# Grow the ivy for this iteration
IVY
.
grow
(
ob
)
# Print the proportion of ivy growth to console
if
(
IVY
.
maxLength
/
maxLength
*
100
)
>
10
*
startPercent
//
10
:
print
(
'
%0.2f%% of Ivy nodes have grown
'
%
\
(
IVY
.
maxLength
/
maxLength
*
100
))
startPercent
+=
10
if
IVY
.
maxLength
/
maxLength
>
1
:
print
(
"
Halting Growth
"
)
# Make an iterator to check if all are alive
checkAliveIter
=
(
r
.
alive
for
r
in
IVY
.
ivyRoots
)
# Create the curve and leaf geometry
createIvyGeometry
(
IVY
,
self
.
growLeaves
)
print
(
"
Geometry Generation Complete
"
)
print
(
"
Ivy generated in %0.2f s
"
%
(
time
.
time
()
-
t
))
self
.
updateIvy
=
False
return
{
'
FINISHED
'
}
return
{
'
PASS_THROUGH
'
}
def
draw
(
self
,
context
):
layout
=
self
.
layout
row
=
layout
.
row
()
row
.
alignment
=
'
EXPAND
'
row
.
prop
(
self
,
'
updateIvy
'
,
icon
=
'
CURVE_DATA
'
)
row
=
layout
.
row
()
properties
=
row
.
operator
(
'
curve.ivy_gen
'
,
text
=
"
Add New Ivy
"
)
properties
.
randomSeed
=
self
.
randomSeed
properties
.
maxTime
=
self
.
maxTime
properties
.
maxIvyLength
=
self
.
maxIvyLength
properties
.
ivySize
=
self
.
ivySize
properties
.
maxFloatLength
=
self
.
maxFloatLength
properties
.
maxAdhesionDistance
=
self
.
maxAdhesionDistance
properties
.
primaryWeight
=
self
.
primaryWeight
properties
.
randomWeight
=
self
.
randomWeight
properties
.
gravityWeight
=
self
.
gravityWeight
properties
.
adhesionWeight
=
self
.
adhesionWeight
properties
.
branchingProbability
=
self
.
branchingProbability
properties
.
leafProbability
=
self
.
leafProbability
properties
.
ivyBranchSize
=
self
.
ivyBranchSize
properties
.
ivyLeafSize
=
self
.
ivyLeafSize
row
=
layout
.
row
()
row
.
operator
(
'
curve.ivy_gen
'
,
text
=
"
Add New Default Ivy
"
)
row
=
layout
.
row
()
row
.
prop
(
self
,
'
growLeaves
'
)
box
=
layout
.
box
()
box
.
label
(
"
Generation Settings
"
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
randomSeed
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
maxTime
'
)
box
=
layout
.
box
()
box
.
label
(
"
Size Settings
"
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
maxIvyLength
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
ivySize
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
maxFloatLength
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
maxAdhesionDistance
'
)
box
=
layout
.
box
()
box
.
label
(
"
Weight Settings
"
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
primaryWeight
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
randomWeight
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
gravityWeight
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
adhesionWeight
'
)
box
=
layout
.
box
()
box
.
label
(
"
Branch Settings
"
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
branchingProbability
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
ivyBranchSize
'
)
if
self
.
growLeaves
:
box
=
layout
.
box
()
box
.
label
(
"
Leaf Settings
"
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
ivyLeafSize
'
)
row
=
box
.
row
()
row
.
prop
(
self
,
'
leafProbability
'
)
def
menu_func
(
self
,
context
):
self
.
layout
.
operator
(
IvyGen
.
bl_idname
,
text
=
"
Add Ivy to Mesh
"
,
icon
=
'
PLUGIN
'
).
updateIvy
=
True
def
register
():
bpy
.
utils
.
register_module
(
__name__
)
bpy
.
types
.
INFO_MT_curve_add
.
append
(
menu_func
)
def
unregister
():
bpy
.
types
.
INFO_MT_curve_add
.
remove
(
menu_func
)
bpy
.
utils
.
unregister_module
(
__name__
)
if
__name__
==
"
__main__
"
:
register
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment