1
$\begingroup$

Given a list of coordinates specifying the path of a brush stroke, I would like to have a python script that automatically applies the Cloth brush stroke like in the image bellow.

What I want my code to do

After modifying the code from this post, the code bellow should:

  • Remove all objects from the scene
  • Add an Icosphere to the scene
  • Apply a stroke with the cloth brush tool (which it fails to do)

If you uncomment line number 64 however, the code does successfully apply a stroke with the Blob brush tool instead.

So my question is how I would go about modifying the code so that it successfully applies a cloth brush stroke?

Alternatively, are there any alternative methods for procedurally applying similar looking wrinkles to the mesh? As long as I can specify where the wrinkles appear, that is good enough for my purposes. The more control my code has, the better!

import bpy
import numpy as np

# Override context while stroke is applied
# https://github.com/christian-vorhemus/procedural-3d-image-generation/blob/master/blenderBackgroundTask.py#L54
def context_override():
    for window in bpy.context.window_manager.windows:
        screen = window.screen
        for area in screen.areas:
            if area.type == 'VIEW_3D':
                for region in area.regions:
                    if region.type == 'WINDOW':
                        return {'window': window, 'screen': screen, 'area': area, 'region': region, 'scene': bpy.context.scene} 

# Clear all objects
try:
    bpy.ops.object.mode_set(mode='OBJECT')
except:
    pass
for obj in bpy.context.scene.objects:
    obj.select_set(True)
bpy.ops.object.delete()

# Create basic ico_sphere with 7 subdivisions
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=7)
bpy.ops.object.mode_set(mode='SCULPT')
bpy.data.objects[0].select_set(True)
bpy.context.scene.tool_settings.sculpt.use_symmetry_x = False

# Define path of stroke
num_steps = 10
steps = np.linspace(0, np.pi, num_steps, endpoint=False)
points = []
for i, s in enumerate(steps):
    px = np.sin(s)
    py = np.cos(s)
    pz = 0
    points.append([px, py, pz])

# Define stroke parameters
strokes = []
for i, p in enumerate(points):
    stroke = {    
    "name": "stroke",
    "mouse": (0, 0),
    "pen_flip": False,
    "is_start": True if i==0 else False,
    "location": p,
    "size": 0.5,
    "pressure": 1.0,
    "time": float(i),
    "mouse_event" : (0, 0),
    "x_tilt" : 0,
    "y_tilt" : 0}
    strokes.append(stroke)

# Set brush settings
bpy.data.scenes["Scene"].tool_settings.unified_paint_settings.use_locked_size = "SCENE"
bpy.data.scenes["Scene"].tool_settings.unified_paint_settings.unprojected_radius = 0.5


# Uncomment line bellow to switch between BLOB brush and CLOTH brush
bpy.ops.paint.brush_select(sculpt_tool='CLOTH', toggle=False)
# bpy.ops.paint.brush_select(sculpt_tool='BLOB', toggle=False)

# More brush settings
bpy.data.brushes["Blob"].strength = 0.5
bpy.data.brushes["Blob"].curve_preset = "SMOOTH"
bpy.data.brushes["Blob"].auto_smooth_factor = 1.0

# Apply stroke
bpy.ops.sculpt.brush_stroke(context_override(), stroke=strokes)
$\endgroup$

1 Answer 1

1
$\begingroup$

Use "Cloth" instead of "Blob" within these lines. Then you might need to adjust the values to get better wrinkles.

bpy.data.brushes["Cloth"].strength = 0.5
bpy.data.brushes["Cloth"].curve_preset = "SMOOTH"
bpy.data.brushes["Cloth"].auto_smooth_factor = 1.0

enter image description here

$\endgroup$
2
  • 1
    $\begingroup$ Oh wow, don't know how I missed that! Thanks heaps for pointing that out though! $\endgroup$ Commented Aug 17, 2022 at 7:43
  • $\begingroup$ yeah i thought so you just missed it. once in a while we need an extra pair of eyes to look at something :) $\endgroup$
    – Harry McKenzie
    Commented Aug 17, 2022 at 7:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .