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:
authormeta-androcto <meta.androcto1@gmail.com>2017-03-19 06:19:53 +0300
committermeta-androcto <meta.androcto1@gmail.com>2017-03-19 06:19:53 +0300
commitb534a0dc37c69c85f1a06f2a8663327ea603e945 (patch)
tree0312b5d6fb77974744075eb62fd6226f0491b49e /add_curve_extra_objects
parent8c378c52c83757b9e78d5a98581bf240ed31a1ec (diff)
Update add_curve_extra_objects add bounce spline/sporo fit, update curves galore T50943
Diffstat (limited to 'add_curve_extra_objects')
-rw-r--r--add_curve_extra_objects/__init__.py2
-rw-r--r--add_curve_extra_objects/add_curve_aceous_galore.py256
-rw-r--r--add_curve_extra_objects/add_curve_spirofit_bouncespline.py630
3 files changed, 773 insertions, 115 deletions
diff --git a/add_curve_extra_objects/__init__.py b/add_curve_extra_objects/__init__.py
index 05a8e873..f328ed9d 100644
--- a/add_curve_extra_objects/__init__.py
+++ b/add_curve_extra_objects/__init__.py
@@ -43,6 +43,7 @@ if "bpy" in locals():
importlib.reload(add_curve_celtic_links)
importlib.reload(add_curve_braid)
importlib.reload(add_curve_simple)
+ importlib.reload(add_curve_spirofit_bouncespline)
else:
from . import add_curve_aceous_galore
@@ -54,6 +55,7 @@ else:
from . import add_curve_celtic_links
from . import add_curve_braid
from . import add_curve_simple
+ from . import add_curve_spirofit_bouncespline
import bpy
from bpy.types import Menu, AddonPreferences
diff --git a/add_curve_extra_objects/add_curve_aceous_galore.py b/add_curve_extra_objects/add_curve_aceous_galore.py
index 6a7ac654..649bf559 100644
--- a/add_curve_extra_objects/add_curve_aceous_galore.py
+++ b/add_curve_extra_objects/add_curve_aceous_galore.py
@@ -51,6 +51,7 @@ from math import (
)
import mathutils.noise as Noise
from bpy.types import Operator
+
# ------------------------------------------------------------
# Some functions to use with others:
# ------------------------------------------------------------
@@ -118,20 +119,6 @@ def vTurbNoise(x, y, z, iScale=0.25, Size=1.0, Depth=6, Hard=0, Basis=0, Seed=0)
tz = vTurb[2]*iScale
return tx, ty, tz
-
-#------------------------------------------------------------
-# Axis: ( used in 3DCurve Turbulence )
-def AxisFlip(x, y, z, x_axis=1, y_axis=1, z_axis=1, flip=0):
- if flip != 0:
- flip *= -1
- else:
- flip = 1
- x *= x_axis*flip
- y *= y_axis*flip
- z *= z_axis*flip
- return x, y, z
-
-
# -------------------------------------------------------------------
# 2D Curve shape functions:
# -------------------------------------------------------------------
@@ -193,12 +180,12 @@ def ProfileCurve(type=0, a=0.25, b=0.25):
return newpoints
# ------------------------------------------------------------
-# 2DCurve: Arrows
+# 2DCurve: Arrow
def ArrowCurve(type=1, a=1.0, b=0.5):
"""
ArrowCurve( type=1, a=1.0, b=0.5, c=1.0 )
- Create arrow curves
+ Create arrow curve
Parameters:
type - select type, Arrow1, Arrow2
@@ -235,7 +222,7 @@ def RectCurve(type=1, a=1.0, b=0.5, c=1.0):
"""
RectCurve( type=1, a=1.0, b=0.5, c=1.0 )
- Create square / rectangle curves
+ Create square / rectangle curve
Parameters:
type - select type, Square, Rounded square 1, Rounded square 2
@@ -402,7 +389,7 @@ def ArcCurve(sides=6, startangle=0.0, endangle=90.0, innerradius=0.5, outerradiu
newpoints.append([x1, y1, 0])
i += 1
- # if type ==0:
+ # if type == 1:
# Arc: turn cyclic curve flag off!
# Segment:
@@ -538,57 +525,8 @@ def SplatCurve(sides=24, scale=1.0, seed=0, basis=0, radius=1.0):
i += 1
return newpoints
-# -----------------------------------------------------------
-# 3D curve shape functions:
-# -----------------------------------------------------------
-
-# ------------------------------------------------------------
-# 3DCurve: Helix:
-def HelixCurve(number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0):
- """
- HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 )
-
- Create helix curve
-
- Parameters:
- number - the number of points
- (type=int)
- height - height
- (type=float)
- startangle - startangle
- (type=float)
- endangle - endangle
- (type=float)
- width - width
- (type=float)
- a - a
- (type=float)
- b - b
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- angle = (2.0/360.0)*(endangle-startangle)
- step = angle/(number-1)
- h = height/angle
- start = (startangle*2.0/360.0)
- a /= angle
- i = 0
- while i < number:
- t = (i*step+start)
- x = sin((t*pi)) * (1.0 + cos(t * pi * a - (b * pi))) * (0.25 * width)
- y = cos((t*pi)) * (1.0 + cos(t * pi * a - (b * pi))) * (0.25 * width)
- z = (t * h) - h*start
- newpoints.append([x, y, z])
- i += 1
- return newpoints
-
#------------------------------------------------------------
# Cycloid curve
-
def CycloidCurve(number=100, type=0, R=4.0, r=1.0, d=1.0):
"""
CycloidCurve( number=100, type=0, a=4.0, b=1.0 )
@@ -645,12 +583,58 @@ def CycloidCurve(number=100, type=0, R=4.0, r=1.0, d=1.0):
i+=1
return newpoints
+# -----------------------------------------------------------
+# 3D curve shape functions:
+# -----------------------------------------------------------
+
+# ------------------------------------------------------------
+# 3DCurve: Helix:
+def HelixCurve(number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0):
+ """
+ HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 )
+
+ Create helix curve
+
+ Parameters:
+ number - the number of points
+ (type=int)
+ height - height
+ (type=float)
+ startangle - startangle
+ (type=float)
+ endangle - endangle
+ (type=float)
+ width - width
+ (type=float)
+ a - a
+ (type=float)
+ b - b
+ (type=float)
+ Returns:
+ a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
+ (type=list)
+ """
+
+ newpoints = []
+ angle = (2.0/360.0)*(endangle-startangle)
+ step = angle/(number-1)
+ h = height/angle
+ start = (startangle*2.0/360.0)
+ a /= angle
+ i = 0
+ while i < number:
+ t = (i*step+start)
+ x = sin((t*pi)) * (1.0 + cos(t * pi * a - (b * pi))) * (0.25 * width)
+ y = cos((t*pi)) * (1.0 + cos(t * pi * a - (b * pi))) * (0.25 * width)
+ z = (t * h) - h*start
+ newpoints.append([x, y, z])
+ i += 1
+ return newpoints
+
#------------------------------------------------------------
# 3D Noise curve
-def NoiseCurve(number=100, length=2.0, scale=1.0, octaves=6, basis=1, seed=0, type=0):
+def NoiseCurve(type=0, number=100, length=2.0, size=0.5, scale=[0.5,0.5,0.5], taper=0.0, octaves=2, basis=0, seed=0):
"""
- NoiseCurve( number=100, length=2.0, scale=1.0, octaves=2, basis=1, seed=0, type=1 )
-
Create noise curve
Parameters:
@@ -658,7 +642,11 @@ def NoiseCurve(number=100, length=2.0, scale=1.0, octaves=6, basis=1, seed=0, ty
(type=int)
length - curve length
(type=float)
- scale - noise scale
+ size - noise size
+ (type=float)
+ scale - noise intensity scale x,y,z
+ (type=list)
+ taper - taper scale
(type=float)
basis - noise basis
(type=int)
@@ -671,31 +659,39 @@ def NoiseCurve(number=100, length=2.0, scale=1.0, octaves=6, basis=1, seed=0, ty
(type=list)
"""
- rand = randnum(-100,100,seed)
newpoints = []
step = (length/number)
i = 0
if type == 1:
- # noise knot
+ # noise circle / arc
while i < number:
- t = ((i*step)+rand)
- v = vTurbNoise(t,t,t, scale, 1.0, octaves, 0, basis, seed)
+ t = i*step
+ v = vTurbNoise(t, t, t, 1.0, size, octaves, 0, basis, seed)
+ x = sin(t*pi)*2.0 + (v[0] * scale[0])
+ y = cos(t*pi)*2.0 + (v[1] * scale[1])
+ z = v[2]*scale[2]
+ newpoints.append([x, y, z])
+ i += 1
+ elif type == 2:
+ # noise knot / ball
+ while i < number:
+ t = i*step
+ v = vTurbNoise(t,t,t, scale[2], 1.0, octaves, 0, basis, seed)
newpoints.append([v[0], v[1], v[2]])
i+=1
else:
# noise linear
while i < number:
t = i*step
- tt = t+rand
- v = vTurbNoise(t,t,t, scale, 1.0, octaves, 0, basis, seed)
- x = t
- y = v[1]
- z = v[2]
+ tap = length-taper*t
+ v = vTurbNoise(t,t,t, 1.0, size, octaves, 0, basis, seed)
+ x = t + v[0] * (scale[0]/length)
+ y = v[1] * (scale[1]/length) * tap
+ z = v[2] * (scale[2]/length) * tap
newpoints.append([x,y,z])
i+=1
return newpoints
-
# ------------------------------------------------------------
# calculates the matrix for the new object
# depending on user pref
@@ -841,6 +837,12 @@ def main(context, self, align_matrix):
self.seed,
self.basis,
outerRadius)
+ if proType == 'Cycloid':
+ verts = CycloidCurve(self.cycloPoints,
+ self.cycloType,
+ self.cyclo_a,
+ self.cyclo_b,
+ self.cyclo_d)
if proType == 'Helix':
verts = HelixCurve(self.helixPoints,
self.helixHeight,
@@ -849,20 +851,16 @@ def main(context, self, align_matrix):
self.helixWidth,
self.helix_a,
self.helix_b)
- if proType == 'Cycloid':
- verts = CycloidCurve(self.cycloPoints,
- self.cycloType,
- self.cyclo_a,
- self.cyclo_b,
- self.cyclo_d)
if proType == 'Noise':
- verts = NoiseCurve(self.noisePoints,
+ verts = NoiseCurve(self.noiseType,
+ self.noisePoints,
self.noiseLength,
- self.noiseScale,
+ self.noiseSize,
+ [self.noiseScaleX, self.noiseScaleY, self.noiseScaleZ],
+ self.noiseTaper,
self.noiseOctaves,
self.noiseBasis,
- self.noiseSeed,
- self.noiseType)
+ self.noiseSeed)
# turn verts into array
vertArray = vertsToPoints(verts, splineType)
@@ -928,6 +926,7 @@ class Curveaceous_galore(Operator):
('VECTOR', 'Vector', 'VECTOR'),
('AUTOMATIC', 'Auto', 'AUTOMATIC')]
handleType = EnumProperty(name="Handle type",
+ default='AUTOMATIC',
description="bezier handles type",
items=bezHandles)
@@ -1078,7 +1077,7 @@ class Curveaceous_galore(Operator):
min=3, soft_min=3,
description="Resolution")
cycloType = IntProperty(name="Type",
- default=0,
+ default=1,
min=0, soft_min=0,
max=2, soft_max=2,
description="Type: Cycloid , Hypocycloid / Hypotrochoid , Epicycloid / Epitrochoid")
@@ -1095,6 +1094,11 @@ class Curveaceous_galore(Operator):
description="Cycloid: d distance")
# Noise properties
+ noiseType = IntProperty(name="Type",
+ default=0,
+ min=0, soft_min=0,
+ max=2, soft_max=2,
+ description="Noise curve type: Linear, Circular or Knot")
noisePoints = IntProperty(name="Resolution",
default=100,
min=3, soft_min=3,
@@ -1103,29 +1107,42 @@ class Curveaceous_galore(Operator):
default=2.0,
min=0.01, soft_min=0.01,
description="Curve Length")
- noiseScale = FloatProperty(name="Noise scale",
- default=1.0,
+ noiseSize = FloatProperty(name="Noise size",
+ default=0.25,
+ min=0.0001, soft_min=0.0001,
+ description="Noise size")
+ noiseScaleX = FloatProperty(name="Noise x",
+ default=0.5,
min=0.0001, soft_min=0.0001,
- description="Noise scale")
+ description="Noise x")
+ noiseScaleY = FloatProperty(name="Noise y",
+ default=0.5,
+ min=0.0001, soft_min=0.0001,
+ description="Noise y")
+ noiseScaleZ = FloatProperty(name="Noise z",
+ default=0.5,
+ min=0.0001, soft_min=0.0001,
+ description="Noise z")
+ noiseTaper = FloatProperty(name="Noise taper",
+ default=0.0,
+ min=0.0001, soft_min=0.0001,
+ max=1.0, soft_max=1.0,
+ description="Noise taper")
noiseOctaves = IntProperty(name="Octaves",
default=2,
- min=0, soft_min=0,
+ min=1, soft_min=1,
max=16, soft_max=16,
description="Basis")
noiseBasis = IntProperty(name="Basis",
default=0,
min=0, soft_min=0,
- max=14, soft_max=14,
+ max=9, soft_max=9,
description="Basis")
noiseSeed = IntProperty(name="Seed",
default=1,
min=0, soft_min=0,
description="Random Seed")
- noiseType = IntProperty(name="Type",
- default=0,
- min=0, soft_min=0,
- max=1, soft_max=1,
- description="Noise curve type: Linear or Knot")
+
##### DRAW #####
def draw(self, context):
@@ -1193,6 +1210,14 @@ class Curveaceous_galore(Operator):
box.prop(self, 'seed')
box.prop(self, 'basis')
+ elif self.ProfileType == 'Cycloid':
+ box.prop(self, 'cycloPoints')
+ box.prop(self, 'cycloType')
+ box.prop(self, 'cyclo_a')
+ box.prop(self, 'cyclo_b')
+ if self.cycloType != 0:
+ box.prop(self, 'cyclo_d')
+
elif self.ProfileType == 'Helix':
box.prop(self, 'helixPoints')
box.prop(self, 'helixHeight')
@@ -1202,18 +1227,17 @@ class Curveaceous_galore(Operator):
box.prop(self, 'helix_a')
box.prop(self, 'helix_b')
- elif self.ProfileType == 'Cycloid':
- box.prop(self, 'cycloPoints')
- box.prop(self, 'cycloType')
- box.prop(self, 'cyclo_a')
- box.prop(self, 'cyclo_b')
- box.prop(self, 'cyclo_d')
-
elif self.ProfileType == 'Noise':
- box.prop(self, 'noisePoints')
box.prop(self, 'noiseType')
+ box.prop(self, 'noisePoints')
box.prop(self, 'noiseLength')
- box.prop(self, 'noiseScale')
+ if self.noiseType in [0,1]:
+ box.prop(self, 'noiseSize')
+ box.prop(self, 'noiseScaleX')
+ box.prop(self, 'noiseScaleY')
+ box.prop(self, 'noiseScaleZ')
+ if self.noiseType == 0:
+ box.prop(self, 'noiseTaper')
box.prop(self, 'noiseOctaves')
box.prop(self, 'noiseBasis')
box.prop(self, 'noiseSeed')
@@ -1223,11 +1247,10 @@ class Curveaceous_galore(Operator):
col.row().prop(self, 'outputType', expand=True)
# output options
- box = layout.box()
if self.outputType == 'NURBS':
- box.prop(self, 'order_u')
+ col.prop(self, 'order_u')
elif self.outputType == 'BEZIER':
- box.row().prop(self, 'handleType', expand=True)
+ col.row().prop(self, 'handleType', expand=True)
##### POLL #####
@classmethod
@@ -1254,7 +1277,10 @@ class Curveaceous_galore(Operator):
else:
self.use_cyclic_u = True
else:
- self.use_cyclic_u = True
+ if self.ProfileType == 'Arc' and self.arcType == 1:
+ self.use_cyclic_u = False
+ else:
+ self.use_cyclic_u = True
# main function
main(context, self, self.align_matrix or Matrix())
diff --git a/add_curve_extra_objects/add_curve_spirofit_bouncespline.py b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py
new file mode 100644
index 00000000..9b5d7aee
--- /dev/null
+++ b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py
@@ -0,0 +1,630 @@
+# ##### 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 #####
+
+
+bl_info = {
+ "name": "SpiroFit and BounceSpline",
+ "author": "Jimmy Hazevoet, Antonio Osprite, Liero, Atom",
+ "version": (0, 2, 0),
+ "blender": (2, 78, 0),
+ "location": "Toolshelf > Misc Tab",
+ "description": "SpiroFit and BounceSpline adds splines to Mesh",
+ "warning": "",
+ "wiki_url": "",
+ "category": "Object",
+}
+
+
+import bpy
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ )
+from mathutils import (
+ Matrix,
+ Vector,
+ )
+from math import (
+ sin,
+ cos,
+ pi
+ )
+from bpy.types import Operator
+import random as r
+
+
+# ------------------------------------------------------------
+#
+def use_random_seed(seed):
+ r.seed(seed)
+ return
+
+# ------------------------------------------------------------
+# Generate new curve object from given points
+# ------------------------------------------------------------
+
+def add_curve_object(verts, matrix,
+ x_ray=False,
+ spline_type='BEZIER',
+ spline_resolution=12,
+ bevel=0.0,
+ bevel_resolution=0,
+ spline_random_radius=0.0):
+
+ curve = bpy.data.curves.new('Spline','CURVE')
+ curve.dimensions = '3D'
+ spline = curve.splines.new(spline_type)
+ cur = bpy.data.objects.new('Curve',curve)
+
+ if spline_type == 'BEZIER':
+ spline.bezier_points.add(int(len(verts)-1))
+ for i in range(len(verts)):
+ spline.bezier_points[i].co = verts[i]
+ spline.bezier_points[i].handle_right_type = 'AUTO'
+ spline.bezier_points[i].handle_left_type = 'AUTO'
+ spline.bezier_points[i].radius += r.random() * spline_random_radius
+ else:
+ spline.points.add(int(len(verts)-1))
+ for i in range(len(verts)):
+ spline.points[i].co = verts[i][0], verts[i][1], verts[i][2], 1
+
+ bpy.context.scene.objects.link(cur)
+ cur.data.use_uv_as_generated = True
+ cur.data.resolution_u = spline_resolution
+ cur.data.fill_mode = 'FULL'
+ cur.data.bevel_depth = bevel
+ cur.data.bevel_resolution = bevel_resolution
+ cur.matrix_world = matrix
+ if x_ray:
+ cur.show_x_ray = x_ray
+ return
+
+
+# ------------------------------------------------------------
+# Spirofit, original blender 2.45 script by: Antonio Osprite
+# http://www.kino3d.com/forum/viewtopic.php?t=5374
+# ------------------------------------------------------------
+
+def distance(v1, v2):
+ d = (Vector(v1) - Vector(v2)).length
+ return d
+
+
+def spiral_point(step, radius, z_coord, spires, waves, wave_height, rndm):
+ x = radius * cos(spires*step) + r.random()*rndm
+ y = radius * sin(spires*step) + r.random()*rndm
+ z = z_coord + (cos(waves*step*pi)*wave_height) + r.random()*rndm
+ return [x, y, z]
+
+
+def do_object_mapping(obj, vert, center, offset):
+ intersections = []
+ ray = Vector(vert)
+ orig = Vector(center)
+ direction = ray - orig
+ poly = obj.data.polygons
+ for f in poly:
+ foo, hit, nor, index = obj.ray_cast(orig, direction)
+ if hit:
+ intersections.append(hit + offset * nor)
+
+ if len(intersections) > 0:
+ mapped = min([(distance(i, vert), i) for i in intersections])[1]
+ else:
+ mapped = orig
+
+ return [mapped[0], mapped[1], mapped[2]]
+
+
+def spirofit_spline(obj,
+ spires=4,
+ spire_resolution=4,
+ waves=0,
+ wave_height=0.0,
+ rndm_spire=0.0,
+ offset=0.0):
+
+ points = []
+ bb = obj.bound_box
+ bb_xmin = min([ v[0] for v in bb ])
+ bb_ymin = min([ v[1] for v in bb ])
+ bb_zmin = min([ v[2] for v in bb ])
+ bb_xmax = max([ v[0] for v in bb ])
+ bb_ymax = max([ v[1] for v in bb ])
+ bb_zmax = max([ v[2] for v in bb ])
+
+ radius = distance([bb_xmax, bb_ymax, bb_zmin], [bb_xmin, bb_ymin, bb_zmin]) / 2.0
+ height = bb_zmax - bb_zmin
+ cx = (bb_xmax + bb_xmin) / 2.0
+ cy = (bb_ymax + bb_ymin) / 2.0
+ center = [cx, cy, bb_zmin]
+
+ cp = spiral_point(bb_zmin, radius, bb_zmin, spires, waves, wave_height, 0)
+ cp = do_object_mapping(obj, cp, center, offset)
+
+ steps = spires * spire_resolution
+ for i in range(1, steps+1):
+ t = bb_zmin + (2*pi / steps) * i
+ z = bb_zmin + (float(height) / steps) * i
+ center = [cx, cy, z]
+
+ cp = spiral_point(t, radius, z, spires, waves, wave_height, rndm_spire)
+ cp = do_object_mapping(obj, cp, center, offset)
+
+ points.append(cp)
+ return points
+
+
+# ------------------------------------------------------------
+
+class SpiroFitSpline(bpy.types.Operator):
+ bl_idname = "wm.add_spirofit_spline"
+ bl_label = "SpiroFit"
+ bl_description="Adds a spirofit to selected mesh"
+ bl_options = {'REGISTER', 'UNDO', 'PRESET'}
+
+ spire_resolution = bpy.props.IntProperty(name="Spire Resolution",
+ default=4,
+ min=3, soft_min=3,
+ max=128, soft_max=128,
+ description="Spire Resolution")
+
+ spires = bpy.props.IntProperty(name="Spires",
+ default=4,
+ min=1, soft_min=1,
+ max=512, soft_max=512,
+ description="Number of Spire Turns")
+
+ waves = bpy.props.IntProperty(name="Waves Amount",
+ default=0,
+ min=0, soft_min=0,
+ description="Waves amount")
+
+ wave_height = bpy.props.FloatProperty(name="Wave Intensity",
+ default=0.1,
+ min=0.0, soft_min=0.0,
+ description="Wave intensity scale")
+
+ rndm_spire = bpy.props.FloatProperty(name="Randomize",
+ default=0.0,
+ min=0.0, soft_min=0.0,
+ description="Randomize spire")
+
+ offset = bpy.props.FloatProperty(name="Offset",
+ default=0.0,
+ description="Use normal direction to offset spline")
+
+
+ splineTypes = [
+ ('POLY', 'Poly', 'POLY'),
+ ('BEZIER', 'Bezier', 'BEZIER')]
+ spline_type = bpy.props.EnumProperty(name="Spline type",
+ default='BEZIER',
+ description="Spline type",
+ items=splineTypes)
+
+ spline_resolution = bpy.props.IntProperty(name="Resolution u",
+ default=12,
+ min=0, soft_min=0,
+ max=64, soft_max=64,
+ description="Curve resolution u")
+
+ bevel = bpy.props.FloatProperty(name="Bevel radius",
+ default=0.0,
+ min=0.0, soft_min=0.0,
+ description="Bevel depth")
+
+ bevel_res = bpy.props.IntProperty(name="Bevel resolution",
+ default=0,
+ min=0, soft_min=0,
+ max=32, soft_max=32,
+ description="Bevel resolution")
+
+ spline_random_radius = bpy.props.FloatProperty(name="Random bevel radius",
+ default=0.0,
+ min=0.0, soft_min=0.0,
+ description="Random radius amount")
+
+ random_seed = bpy.props.IntProperty(name="Random seed",
+ default=1,
+ min=0, soft_min=0,
+ description="Random seed number")
+
+ x_ray = bpy.props.BoolProperty(name="X-Ray",
+ default=True,
+ description = "Make the object draw in front of others")
+
+ updateSpline = bpy.props.BoolProperty(name="Update", description="Update spline", default=False)
+
+
+ @classmethod
+ def poll(self, context):
+ ob = context.active_object
+ return ((ob is not None) and
+ (ob.type == 'MESH') and
+ (context.mode == 'OBJECT'))
+
+
+ def invoke(self, context, event):
+ self.updateSpline = True
+ return self.execute(context)
+
+
+ def execute(self, context):
+ if not self.updateSpline:
+ return {'PASS_THROUGH'}
+
+ undo = context.user_preferences.edit.use_global_undo
+ context.user_preferences.edit.use_global_undo = False
+
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ obj = context.active_object
+ matrix = obj.matrix_world
+
+ if self.random_seed:
+ use_random_seed(self.random_seed)
+
+ points = spirofit_spline(obj,
+ self.spires,
+ self.spire_resolution,
+ self.waves,
+ self.wave_height,
+ self.rndm_spire,
+ self.offset)
+
+ add_curve_object(points,
+ matrix,
+ self.x_ray,
+ self.spline_type,
+ self.spline_resolution,
+ self.bevel,
+ self.bevel_res,
+ self.spline_random_radius)
+
+ context.user_preferences.edit.use_global_undo = undo
+ return {'FINISHED'}
+
+
+ def draw(self, context):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+
+ row.prop(self, 'x_ray', toggle=True)
+ row.separator()
+
+ row.prop(self, 'updateSpline', toggle=True) #, icon='FILE_REFRESH')
+ row.separator()
+
+ properties = row.operator('wm.add_spirofit_spline', text="Add New")
+ col.separator()
+
+ properties.x_ray = self.x_ray
+
+ properties.spire_resolution = self.spire_resolution
+ properties.spires = self.spires
+ properties.waves = self.waves
+ properties.wave_height = self.wave_height
+ properties.offset = self.offset
+ properties.rndm_spire = self.rndm_spire
+ properties.random_seed = self.random_seed
+
+ properties.spline_type = self.spline_type
+ properties.spline_resolution = self.spline_resolution
+ properties.bevel = self.bevel
+ properties.bevel_res = self.bevel_res
+ properties.spline_random_radius = self.spline_random_radius
+
+ col = layout.column(align=True)
+ col.prop(self, 'spire_resolution')
+ col.prop(self, 'spires')
+ col.prop(self, 'waves')
+ col.prop(self, 'wave_height')
+ col.prop(self, 'offset')
+ col.prop(self, 'rndm_spire')
+ col.prop(self, 'random_seed')
+ col.separator()
+
+ col = layout.column(align=True)
+ col.prop(self, 'spline_type', text="")
+ col.separator()
+ col.prop(self, 'spline_resolution')
+ col.prop(self, 'bevel')
+ if self.spline_type == 'BEZIER':
+ col.prop(self, 'spline_random_radius')
+ col.prop(self, 'bevel_res')
+
+
+# ------------------------------------------------------------
+# Bounce spline / Fiber mesh
+# Original script by Liero and Atom
+# https://blenderartists.org/forum/showthread.php?331750-Fiber-Mesh-Emulation
+# ------------------------------------------------------------
+
+def noise(var=1):
+ rand = Vector((r.gauss(0,1), r.gauss(0,1), r.gauss(0,1)))
+ vec = rand.normalized() * var
+ return vec
+
+
+def bounce_spline(obj,
+ number=1000,
+ ang_noise=0.25,
+ offset=0.0,
+ extra=50,
+ active_face=False):
+
+ dist, points = 1000, []
+ poly = obj.data.polygons
+
+ if active_face:
+ try:
+ n = poly.active
+ except:
+ print("No active face selected")
+ pass
+ else:
+ n = r.randint(0, len(poly)-1)
+
+ end = poly[n].normal.copy() * -1
+ start = poly[n].center
+ points.append(start + offset * end)
+
+ for i in range(number):
+ for ray in range(extra + 1):
+ end += noise(ang_noise)
+ try:
+ foo, hit, nor, index = obj.ray_cast(start, end * dist)
+ except:
+ index = -1
+ if index != -1:
+ start = hit - nor / 10000
+ end = end.reflect(nor).normalized()
+ points.append(hit + offset * nor)
+ break
+ if index == -1:
+ return points
+ return points
+
+# ------------------------------------------------------------
+
+class BounceSpline(bpy.types.Operator):
+ bl_idname = "wm.add_bounce_spline"
+ bl_label = "BounceSpline"
+ bl_description="Adds a bounce spline to selected mesh"
+ bl_options = {'REGISTER', 'UNDO', 'PRESET'}
+
+ random_seed = bpy.props.IntProperty(name="Random seed",
+ default=0,
+ min=0, soft_min=0,
+ description="Random seed number")
+
+ bounce_number = bpy.props.IntProperty(name="Bounces",
+ default=100,
+ min=1, soft_min=1,
+ max=9999, soft_max=9999,
+ description="Number of Bounces")
+
+ ang_noise = bpy.props.FloatProperty(name="Angular noise",
+ default=0.25,
+ min=0.0, soft_min=0.0,
+ description="Add some noise to ray direction")
+
+ offset = bpy.props.FloatProperty(name="Offset",
+ default=0.0,
+ description="Use normal direction to offset spline")
+
+ extra = bpy.props.IntProperty(name="Extra",
+ default=50,
+ min=0, soft_min=0,
+ max=999, soft_max=999,
+ description="Number of extra tries if it fails to hit mesh")
+
+ active_face = bpy.props.BoolProperty(name="Active face",
+ default=False,
+ description = "Starts from active face or a random one")
+
+ splineTypes = [
+ ('POLY', 'Poly', 'POLY'),
+ ('BEZIER', 'Bezier', 'BEZIER')]
+ spline_type = bpy.props.EnumProperty(name="Spline type",
+ default='BEZIER',
+ description="Spline type",
+ items=splineTypes)
+
+ spline_resolution = bpy.props.IntProperty(name="Resolution u",
+ default=12,
+ min=0, soft_min=0,
+ max=64, soft_max=64,
+ description="Curve resolution u")
+
+ bevel = bpy.props.FloatProperty(name="Bevel radius",
+ default=0.0,
+ min=0.0, soft_min=0.0,
+ description="Bevel depth")
+
+ bevel_res = bpy.props.IntProperty(name="Bevel resolution",
+ default=0,
+ min=0, soft_min=0,
+ max=32, soft_max=32,
+ description="Bevel resolution")
+
+ spline_random_radius = bpy.props.FloatProperty(name="Random bevel radius",
+ default=0.0,
+ min=0.0, soft_min=0.0,
+ description="Random radius amount")
+
+ x_ray = bpy.props.BoolProperty(name="X-Ray",
+ default=True,
+ description = "Make the object draw in front of others")
+
+ updateSpline = bpy.props.BoolProperty(name="Update", default=False)
+
+
+ @classmethod
+ def poll(self, context):
+ ob = context.active_object
+ return ((ob is not None) and
+ (ob.type == 'MESH') and
+ (context.mode == 'OBJECT'))
+
+
+ def invoke(self, context, event):
+ self.updateSpline = True
+ return self.execute(context)
+
+
+ def execute(self, context):
+ if not self.updateSpline:
+ return {'PASS_THROUGH'}
+
+ undo = context.user_preferences.edit.use_global_undo
+ context.user_preferences.edit.use_global_undo = False
+
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ obj = context.active_object
+
+ if self.random_seed:
+ use_random_seed(self.random_seed)
+
+ points = bounce_spline(obj,
+ self.bounce_number,
+ self.ang_noise,
+ self.offset,
+ self.extra,
+ self.active_face)
+
+ add_curve_object(points,
+ obj.matrix_world,
+ self.x_ray,
+ self.spline_type,
+ self.spline_resolution,
+ self.bevel,
+ self.bevel_res,
+ self.spline_random_radius)
+
+ context.user_preferences.edit.use_global_undo = undo
+ return {'FINISHED'}
+
+
+ def draw(self, context):
+ layout = self.layout
+ col = layout.column(align=True)
+ row = col.row(align=True)
+
+ row.prop(self, 'x_ray', toggle=True)
+ row.separator()
+
+ row.prop(self, 'updateSpline', toggle=True) #, icon='FILE_REFRESH')
+ row.separator()
+
+ properties = row.operator('wm.add_bounce_spline', text="Add New")
+ col.separator()
+
+ properties.x_ray = self.x_ray
+
+ properties.bounce_number = self.bounce_number
+ properties.ang_noise = self.ang_noise
+ properties.offset = self.offset
+ properties.extra = self.extra
+ properties.random_seed = self.random_seed
+ properties.active_face = self.active_face
+
+ properties.spline_type = self.spline_type
+ properties.spline_resolution = self.spline_resolution
+ properties.bevel = self.bevel
+ properties.bevel_res = self.bevel_res
+ properties.spline_random_radius = self.spline_random_radius
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ col.prop(self, 'bounce_number')
+ col.prop(self, 'ang_noise')
+ col.prop(self, 'offset')
+ col.prop(self, 'extra')
+ col.prop(self, 'random_seed')
+ col.separator()
+ col.prop(self, 'active_face', toggle=False)
+
+ col = layout.column(align=True)
+ col.prop(self, 'spline_type', text="")
+ col.separator()
+ col.prop(self, 'spline_resolution')
+
+ col.prop(self, 'bevel')
+ if self.spline_type == 'BEZIER':
+ col.prop(self, 'spline_random_radius')
+ col.prop(self, 'bevel_res')
+
+
+# ------------------------------------------------------------
+# Tools Panel > Misc
+# ------------------------------------------------------------
+
+class SplinePanel( bpy.types.Panel ):
+ bl_space_type = "VIEW_3D"
+ bl_context = "objectmode"
+ bl_region_type = "TOOLS"
+ bl_label = "Add Spline to Mesh"
+ bl_category = "Create"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw( self, context ):
+ scn = context.scene
+ layout = self.layout
+ col = self.layout.column()
+ col.operator(SpiroFitSpline.bl_idname, icon="FORCE_MAGNETIC")
+ col.separator()
+ col.operator(BounceSpline.bl_idname, icon="FORCE_HARMONIC")
+
+# ------------------------------------------------------------ # icon="CURVE_DATA"
+# Menu: Add > Curve >
+# ------------------------------------------------------------
+
+'''
+def menu_func(self, context):
+ self.layout.operator(SpiroFitSpline.bl_idname, icon="PLUGIN")
+ self.layout.operator(BounceSpline.bl_idname, icon="PLUGIN")
+'''
+
+# ------------------------------------------------------------
+# Register
+# ------------------------------------------------------------
+
+def register():
+ bpy.utils.register_class(SpiroFitSpline)
+ bpy.utils.register_class(BounceSpline)
+ bpy.utils.register_class(SplinePanel)
+
+ #bpy.types.INFO_MT_curve_add.append(menu_func)
+
+def unregister():
+ bpy.utils.unregister_class(SpiroFitSpline)
+ bpy.utils.unregister_class(BounceSpline)
+ bpy.utils.unregister_class(SplinePanel)
+ #bpy.types.INFO_MT_curve_add.remove(menu_func)
+
+if __name__ == "__main__":
+ register()