0
$\begingroup$

I want to assign specific materials to selected faces with the Blender Python API.

This should represent the end of a electrical wire. My goal is to assign a material for the isolation of the wire, one for the end cap and one for the metallic tip. So that it looks kind of like this:

enter image description here

I need the code for selecting the faces as well as assigning the materials to it.

If someone out there can help me I would really appreciate it.

My code so far looks like this:

import bpy 
import math 
import random
import bmesh


#define number of Cables
numberOfCables = 5
count = 0

#define all functions

#clean scene (delete all objects inside
def clean_scene():
    for things in bpy.data.objects:
        bpy.data.objects.remove(things)

clean_scene()

#create Nurbs_Path
def create_Nurbs():
    bpy.ops.curve.primitive_nurbs_path_add(radius = randomRadius, 
            enter_editmode = True, 
            location=(X,Y,0.01))
    return bpy.context.object

#defining a volume for the cable
def create_Cable():    
    bpy.ops.mesh.primitive_cylinder_add(radius=randomRadius, 
            depth=randomLength,
            enter_editmode=True,
            location=(X,Y,0.01))
    return bpy.context.object

#With AnisotropicRandomizePoints(scale=(1,1,0,0)) randomise Vertices in XY Plane!
def AnisotropicRandomizePoints(scale=(1,1,1,0), points=None):
    """Anisotropically randomize the coordinates of NURBS points.
    Accepts a sequence of length four as its first argument,
    with the first three elements scaling the randomization
    applied to X, Y, and Z coordinates and the fourth element
    scaling the randomization applied to W respectively. Uses a
    given list of points if specified, otherwise uses all selected
    points in the active object if in Edit Mode or all points
    in the active object otherwise."""
    if points is None:
        points = [p for s in bpy.context.object.data.splines for p in s.points if p.select or bpy.context.mode not in ('EDIT_CURVE', 'EDIT_SURFACE')]
    points = [*points]
    for p in points:
        for i, v in enumerate(p.co):
            p.co[i] = v + (random.random()*1-1)*scale[i]
            
#loopcutting the Cylinders for flexibility        
def view3d_find( return_area = False ):
# returns first 3d view, normally we get from context
    for area in bpy.context.window.screen.areas:
        if area.type == 'VIEW_3D':
            v3d = area.spaces[0]
            rv3d = v3d.region_3d
            for region in area.regions:
                if region.type == 'WINDOW':
                    if return_area: return region, rv3d, v3d, area
                    return region, rv3d, v3d
    return None, None


#Main Programm

bpy.ops.mesh.primitive_plane_add(location=(0, 0, 0), 
                                    scale=(1, 1, 1))
                                    
bpy.ops.transform.resize(value=(10, 10, 10))


for i in range(numberOfCables):
    
    #define random values for location and size
    X = random.uniform(-1,1)
    Y = random.uniform(-1,1)
    randomRadius = random.randrange(15,50,5)/10000 #random thickness ranging from 3mm to 8mm
    randomLength = random.uniform(.3,1) #random length ranging from 30cm to 1m
    randomSeed = random.uniform(0,10)
    #print(randomRadius)
    
    #Creating the Nurbs_Curve where the Cable is later attached
    obj = create_Nurbs()
    
    #randomise the vertices of the Nurbs_Curve to create different shapes (in XY plane)
    AnisotropicRandomizePoints(scale=(1,1,0,0))
    
    #Old version of randomising vertices -> didn't look very natural          
            #randomly place vertecies to have different "cables"
            #bpy.ops.transform.vertex_random(offset=.5, 
            #        uniform=5, 
            #        normal=5, 
            #        seed=randomSeed, 
            #        wait_for_input=True)
            
    #Toggle into OBJECT Mode to assign the Cable to the Curve
    bpy.ops.object.editmode_toggle()
    
    #Create the Cable
    cable = create_Cable()
    
    #Loopcutting the Cable to make it flexible and can therefor be added to the Curve (Code to line 126)
    region, rv3d, v3d, area = view3d_find(True)

    override = {
        'scene'  : bpy.context.scene,
        'region' : region,
        'area'   : area,
        'space'  : v3d
    }

    bpy.ops.mesh.loopcut_slide(
        override, 
        MESH_OT_loopcut = {
            "number_cuts"           : 100,
            "smoothness"            : 0,     
            "falloff"               : 'SMOOTH', 
            "edge_index"            : 2,
            "mesh_select_mode_init" : (True, False, False),
            "object_index"          : 0
        },
        TRANSFORM_OT_edge_slide = {
            "value"           : 0,
            "mirror"          : False, 
            "snap"            : False,
            "snap_target"     : 'CLOSEST',
            "snap_point"      : (0, 0, 0),
            "snap_align"      : False,
            "snap_normal"     : (0, 0, 0),
            "correct_uv"      : False,
            "release_confirm" : False
        }
    )
    
    #back into EDIT Mode    
    bpy.ops.object.editmode_toggle()
    
    #apply Cylinder to shape of the Curve
    cable.modifiers.new(type='CURVE', name='applyShape')
    
    #Select right Curve (Problem after first NurbsPath name continues with NurbsPath.00x) -> if else loop
    if count == 0:
        cable.modifiers["applyShape"].object =  bpy.data.objects["NurbsPath"]
        cable.modifiers["applyShape"].deform_axis = 'POS_Z'
    else:
        a = "NurbsPath."
        b = str(count).zfill(3)
        cable.modifiers["applyShape"].object =  bpy.data.objects[str(a+b)]
        cable.modifiers["applyShape"].deform_axis = 'POS_Z'
        
    #Increase Count by 1 to go into else loop in line 115
    count += 1
    
    #move Cable along Z axis to align more with Curve
    bpy.ops.transform.translate(value=(0, 0, 0.6))
    
    #back into OBJECT Mode    
    bpy.ops.object.editmode_toggle()
    
    #Select faces which are bordered by more than 10 edges -> Top and Bottom
    bpy.ops.mesh.select_face_by_sides(number=10, type='GREATER')
    
    #inset and extrusion for ferrule (Adernendhülse)
    bpy.ops.mesh.inset(thickness=randomRadius/2, depth=0)
    bpy.ops.mesh.inset(thickness=0, depth=.019)
    
   

This code creates a NurbsPath and randomises its vertices along the XY Plane after that a Cylinder gets assigned to it and the End Caps are extruded so that it looks like an electrical wire.

Any help is highly appreciated! Thanks in advance :)

$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.