[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2158] branches/ivygen/truman_ivy/ add_curve_ivygen.py: - Added maximum growing time property
Andrew Hale
TrumanBlending at gmail.com
Fri Jul 22 06:03:46 CEST 2011
Revision: 2158
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2158
Author: trumanblending
Date: 2011-07-22 04:03:44 +0000 (Fri, 22 Jul 2011)
Log Message:
-----------
- Added maximum growing time property
- Increase speed of leaf generation
- Added property group to store properties
- Added panel to reveal properties
Modified Paths:
--------------
branches/ivygen/truman_ivy/add_curve_ivygen.py
Modified: branches/ivygen/truman_ivy/add_curve_ivygen.py
===================================================================
--- branches/ivygen/truman_ivy/add_curve_ivygen.py 2011-07-21 15:42:09 UTC (rev 2157)
+++ branches/ivygen/truman_ivy/add_curve_ivygen.py 2011-07-22 04:03:44 UTC (rev 2158)
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
bl_info = {
"name": "IvyGen",
@@ -33,11 +33,12 @@
import bpy
-from bpy.props import FloatProperty, IntProperty
+from bpy.props import FloatProperty, IntProperty, BoolProperty, PointerProperty
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 createIvyLeaves(IVY, radius):
@@ -65,27 +66,27 @@
for i in range(10):
for node in root.ivyNodes:
# Find the weight and normalise the smooth adhesion vector
- weight = pow(node.length * prevIvyLength, 0.7)
+ weight = pow(node.length / prevIvyLength, 0.7)
normalAd = node.smoothAdhesionVector.normalized()
# Calculate the ground ivy and the new weight
- groundIvy = max(0.0, -normalAd.dot(Vector((0, 0, 1))))
- weight += groundIvy * pow(1 - node.length * prevIvyLength, 2)
+ groundIvy = max(0.0, -normalAd.z)
+ weight += groundIvy * pow(1 - node.length / prevIvyLength, 2)
# Generate the probability
probability = rand_val()
# If we need to grow a leaf, do so
- if ((probability * weight) > IVY.leafProbability and
- node.smoothAdhesionVector.length != 0.0):
+ if (probability * weight) > IVY.leafProbability:
# Find the alignment weight
alignmentWeight = node.smoothAdhesionVector.length
# Calculate the needed angles
phi = atan2(node.smoothAdhesionVector.y,
node.smoothAdhesionVector.x) - pi / 2
+
theta = (0.5 *
- node.smoothAdhesionVector.angle(Vector((0, 0, -1))))
+ node.smoothAdhesionVector.angle(Vector((0, 0, -1)), 0))
# Generate the random vector
randomVector = Vector((rand_val() - 0.5, rand_val() - 0.5,
@@ -105,18 +106,30 @@
leafSize = local_ivyLeafSize * sizeWeight
currentVert = len(vertList)
- faceList.append((currentVert, currentVert + 1,
+ addF((currentVert, currentVert + 1,
currentVert + 2, currentVert + 3))
# For each of the verts in the list 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 *= local_ivyLeafSize * sizeWeight
+ basisVecY *= local_ivyLeafSize * sizeWeight
+
+ randomVector = Vector((rand_val() - 0.5,
+ rand_val() - 0.5, rand_val() - 0.5))
+
for k1, k2 in signList:
- randomVector = Vector((rand_val() - 0.5,
- rand_val() - 0.5, rand_val() - 0.5))
- tmpPos = Vector((k1 * leafSize, k2 * leafSize, 0.0))
- horiRot = rotMat(theta, 3, 'X')
- tmpPos.rotate(horiRot)
- vertRot = rotMat(phi, 3, 'Z')
- tmpPos.rotate(vertRot)
+ tmpPos = k1 * basisVecX + k2 * basisVecY
tmpPos += (randomVector * local_ivyLeafSize *
sizeWeight * 0.5 + center)
addV(tmpPos)
@@ -250,14 +263,17 @@
ivyLeafSize=1.5,
ivyBranchSize=0.15,
maxFloatLength=0.1,
- maxAdhesionDistance=0.1):
+ maxAdhesionDistance=0.1,
+ randomSeed=1,
+ maxIvyLength=0.0,
+ maxTime=0.0):
self.ivyRoots = deque()
self.primaryWeight = primaryWeight
self.randomWeight = randomWeight
self.gravityWeight = gravityWeight
self.adhesionWeight = adhesionWeight
- self.branchingProbability = 1 - branchingProbability
+ self.branchingProbability = branchingProbability
self.leafProbability = leafProbability
self.ivySize = ivySize
self.ivyLeafSize = ivyLeafSize
@@ -398,6 +414,7 @@
adhesion_vector = nearest_result[0] - loc
adhesion_vector.normalize()
adhesion_vector *= 1.0 - distance / max_l
+ #adhesion_vector *= getFaceWeight(ob.data, nearest_result[2])
return adhesion_vector
@@ -422,6 +439,83 @@
bl_label = "IvyGen"
bl_options = {'REGISTER', 'UNDO'}
+ @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):
+ # Get the properties
+ ivyProps = context.window_manager.ivy_props
+
+ # Get the selected object
+ ob = context.active_object
+
+ # Compute bounding sphere radius
+ radius = computeBoundingSphere(ob)
+
+ # Get the seeding point
+ seedPoint = context.scene.cursor_location
+
+ # Find the distance to the closest point
+ dist = (ob.closest_point_on_mesh(seedPoint)[0] - seedPoint).length
+
+ # If the distance is too far, cancel the operator
+ if dist > (radius * ivyProps.maxFloatLength / 2):
+ print("Invalid Root Location")
+ return {'CANCELLED'}
+
+ # If the point is on the surface move it outward slightly
+ if dist == 0.0:
+ seedPoint += (radius * ivyProps.maxFloatLength / 10 *
+ ob.closest_point_on_mesh(seedPoint)[1])
+
+ # Fix the random seed
+ rand_seed(ivyProps.randomSeed)
+
+ # Make the new ivy
+ IVY = Ivy(**dict(ivyProps.items()))
+
+ # Generate first root and node
+ IVY.seed(seedPoint)
+
+ checkAlive = True
+ checkTime = False
+ maxLength = radius * ivyProps.maxIvyLength
+
+ # If we need to check time set the flag
+ if ivyProps.maxTime != 0.0:
+ checkTime = True
+
+ t = time.time()
+
+ # Grow until 200 roots is reached or backup counter exceeds limit
+ while checkAlive and\
+ (IVY.maxLength < maxLength) and\
+ (not checkTime or (time.time() - t < ivyProps.maxTime)):
+ IVY.grow(radius, ob)
+ checkAliveIter = (r.alive for r in IVY.ivyRoots)
+ checkAlive = False
+ if True in checkAliveIter:
+ checkAlive = True
+
+ # Create the curve and leaf geometry
+ curveOb = createIvyCurves(IVY, radius)
+ leafOb = createIvyLeaves(IVY, radius)
+
+ # Parent the leave to the curve
+ leafOb.parent = curveOb
+
+ print("Ivy generated in %0.2f s" % (time.time() - t))
+ return {'FINISHED'}
+
+
+class IvyProps(bpy.types.PropertyGroup):
maxIvyLength = FloatProperty(name="Max Ivy Length",
description="Maximum ivy length as a proportion"\
"of bounding sphere radius",
@@ -451,12 +545,12 @@
soft_max=1.0)
branchingProbability = FloatProperty(name="Branching Probability",
description="Probability of a new branch forming.",
- default=0.05,
+ default=0.95,
min=0.0,
soft_max=1.0)
leafProbability = FloatProperty(name="Leaf Probability",
description="Probability of a leaf forming.",
- default=0.7,
+ default=0.95,
min=0.0,
soft_max=1.0,)
ivySize = FloatProperty(name="Ivy Size",
@@ -496,7 +590,20 @@
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)
+
+class VIEW3D_PT_tools_ivygen(bpy.types.Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'TOOLS'
+ bl_context = "objectmode"
+ bl_label = "IvyGen"
+
@classmethod
def poll(self, context):
# Check if there's an object and whether it's a mesh
@@ -507,75 +614,71 @@
return True
return False
- def execute(self, context):
- # Get the selected object
- ob = context.active_object
+ def draw(self, context):
+ ivyProps = context.window_manager.ivy_props
+ layout = self.layout
+ row = layout.row()
+ row.alignment = 'EXPAND'
+ row.operator('curve.ivy_gen', text="Generate Ivy")
+ box = layout.box()
+ box.label("Generation Settings")
+ row = box.row()
+ row.prop(ivyProps, 'randomSeed')
+ row = box.row()
+ row.prop(ivyProps, 'maxTime')
+ box = layout.box()
+ box.label("Size Settings")
+ row = box.row()
+ row.prop(ivyProps, 'maxIvyLength')
+ row = box.row()
+ row.prop(ivyProps, 'ivySize')
+ row = box.row()
+ row.prop(ivyProps, 'maxFloatLength')
+ row = box.row()
+ row.prop(ivyProps, 'maxAdhesionDistance')
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list