11
$\begingroup$

So I wish to create and object and set it's shading to 'smooth' using python. It seems simple enough but after trying every method I could find on the internet none of them worked for me. Here's a short example script where the object needs to have smooth shading:

import bpy
from mathutils import Vector

verts = [(0,0,0),(0,5,0),(0.25,5,0),(0.25,0,0),(0,0,5),(0,5,5),(0.25,5,5),(0.25,0,5)]
faces = [(0,1,2,3), (4,5,6,7), (0,4,5,1), (1,5,6,2), (2,6,7,3), (3,7,4,0)]

grat1mesh = bpy.data.meshes.new("grat1")
grat1obj = bpy.data.objects.new("grat1", grat1mesh)
grat1obj.location = (5, -5, 0)
bpy.context.scene.objects.link(grat1obj)
grat1mesh.from_pydata(verts,[],faces)
grat1mesh.update(calc_edges=True)

grat2obj = grat1obj.copy()
grat2obj.data = grat1mesh.copy()
bpy.context.scene.objects.link(grat2obj)
grat2obj.location += Vector((-0.125, 1.25, 1.25))
grat2obj.scale = (2, 0.5, 0.5)

bm = grat1obj.modifiers.new("Chop", 'BOOLEAN')
bm.object = grat2obj
bm.operation = 'DIFFERENCE'
bpy.context.scene.objects.active = grat1obj
bpy.ops.object.modifier_apply(modifier=bm.name)
bpy.context.scene.objects.unlink(grat2obj)

I found this online and tried to place it at the end of the script:

smoothings = []
smoothings.append(face.use_smooth)
me_ob.faces.foreach_set("use_smooth", smoothings)

However this just returned an error on the second line, perhaps as it was from an older website. Obviously using a simple bpy.ops.object.shade_smooth() didn't work and I'm kind of stumped as of what to do here!

$\endgroup$
3
  • 1
    $\begingroup$ If you get an error, please include the text of that error in the question. $\endgroup$ Commented Oct 5, 2017 at 17:00
  • $\begingroup$ @RayMairlot Apologies... On blender 2.79 it returns "Python script fail, look in the console for now..." I don't know of a way of getting a more detailed error response, however. $\endgroup$ Commented Oct 5, 2017 at 17:01
  • 1
    $\begingroup$ You need to look in the console. See: blender.stackexchange.com/questions/6173/… $\endgroup$ Commented Oct 5, 2017 at 17:04

1 Answer 1

19
$\begingroup$

Can set face to smooth in bmesh with

for f in bm.faces:
    f.smooth = True

Or in object mode

mesh = context.object.data
for f in mesh.polygons:
    f.use_smooth = True

The foreach set routines need a correctly sized value list for example

values = [True] * len(mesh.polygons)
mesh.polygons.foreach_set("use_smooth", values)

which is the equivalent of the for loop above.

Remember that when blender started to handle ngons (faces with more than 4 verts) it changed the mesh.faces collection was renamed to mesh.polygons.

$\endgroup$
3
  • $\begingroup$ Thanks! After a while of being a dumbo and thinking that just sticking in 'mesh' instead of 'grat1mesh' it finally worked. oops! $\endgroup$ Commented Oct 5, 2017 at 19:00
  • $\begingroup$ Hey, I was wondering if there is a point in trying to optimize the values array used in the foreach_set with a numpy array like values = np.full(len(mesh.polygons), True, dtype=bool) ? I did a few tests but did not find any speed improvement $\endgroup$
    – Gorgious
    Commented Mar 23, 2021 at 17:16
  • $\begingroup$ Sure python is going to make a list of single value pretty quickly.. it's what is done in between. for example inverting the value for a high poly count. np.invert(values) is going to pants a for loop and prob also a list comp [not v for v in values] $\endgroup$
    – batFINGER
    Commented Mar 23, 2021 at 18:11

You must log in to answer this question.

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