This is a magnetic pole piece for an electric motor (there will be 12 in a circle). The bottom face is a hyperbola, the the top is a circle, and the sides are straight.

I would like the top and bottom curved surfaces to appear smooth when rendering in Cycles, but not create any visible rounding of the corners, or affect the large flat faces, so that even when illuminated sideways the top and bottom surfaces would appear smoothly curving.

I'll be doing a lot more to them algorithmically, so I need something that doesn't modify the topology of the mesh by adding/deleting edges, faces, vertices, etc.

edit: Since I'm generating the mesh algorithmically, I will know the indices of the faces that need to be smoothed. If I can target them for smoothing specifically, this would be the best way for me.

Below is a simplified script that shows how I generate them (I've skipped the math, happy to include it if it helps).

enter image description here enter image description here

enter image description here

xpts_sharp = [ 7.196,  5.606,  4.009,  2.407, 0.803, -0.803, -2.407, 
              -4.009, -5.606, -7.196, -5.08, -4.298, -3.517, -2.735, 
              -1.954, -1.172, -0.391,  0.391, 1.172,  1.954,  2.735, 
               3.517,  4.298,  5.08 ]

ypts_sharp = [ 45.434, 45.657, 45.825, 45.937, 45.993, 45.993, 45.937, 
               45.825, 45.657, 45.434, 32.072, 31.832, 31.605, 31.398, 
               31.219, 31.084, 31.01,  31.01,  31.084, 31.219, 31.398, 
               31.605, 31.832, 32.072 ]

import bpy
import numpy as np

xpts = np.array(xpts_sharp)
ypts = np.array(ypts_sharp)
zpts = np.array([-50.0, 50.0])
scale = 0.1

xptss, yptss, zptss = scale*xpts, scale*ypts, scale*zpts
nxy, nz = len(xptss), len(zptss)

verts = []
for zpt in zptss:
    zapt  = zpt + np.zeros_like(xptss)
    vertz = list(zip(xptss, zapt, yptss))
    verts += vertz
nverts = len(verts)

faces = []
for iz in range(nz-1):
    for ixy in range(nxy):
        v1 = (iz+0)*nxy + (ixy+0)%nxy
        v2 = (iz+0)*nxy + (ixy+1)%nxy
        v3 = (iz+1)*nxy + (ixy+1)%nxy
        v4 = (iz+1)*nxy + (ixy+0)%nxy
        faces.append((v1, v2, v3, v4)[::-1])
face = list(range(nxy))
face = list(range(nverts-nxy, nverts))[::-1]

if 1 == 1:
    name = "pole_piece"

    me = bpy.data.meshes.new(name)
    ob = bpy.data.objects.new(name, me)


    me.from_pydata(verts, [], faces)

    bpy.data.objects[name].select = False
    bpy.data.objects[name].select = True

Set your object to smooth shading.

Add an edge split modifier. Apply it if you wish.
edge split

Depending on the angle setting in the edge split modifier, surfaces will appear smooth shaded preserving sharp edges.
enter image description here

Internally, the modifier splits edges based on the angle of the adjacent faces.
enter image description here

This will add the edge split modifier and "apply" it. The topology will change.

if 1 == 1:
    name = "pole_piece"

    me = bpy.data.meshes.new(name)
    ob = bpy.data.objects.new(name, me)

    scene = bpy.context.scene

    me.from_pydata(verts, [], faces)

    bpy.data.objects[name].select = False
    bpy.data.objects[name].select = True

    for p in ob.data.polygons:
        p.use_smooth = True
    mod = ob.modifiers.new("edge", type='EDGE_SPLIT')
    ob.data = ob.to_mesh(scene, True, 'PREVIEW')
  • $\begingroup$ You can easily add and apply modifiers with python as well. I can extend the answer if you wish. $\endgroup$
    – Leander
    Nov 1 '16 at 10:03
  • $\begingroup$ I added the code, why don't you add the edge split modifier as the last step. Or don't apply it and leave it as a modifier. Maybe edit your answer to what your final goal is. $\endgroup$
    – Leander
    Nov 1 '16 at 10:16
  • $\begingroup$ Ah, I see what you mean - that sounds like one solution - leaving it 'un-applied'. I'll edit the question to explain I don't want to modify the mesh topology. Thanks. $\endgroup$
    – uhoh
    Nov 1 '16 at 10:19
  • $\begingroup$ I've adjusted the question a bit. Oh, since I know which faces I want to smooth - I can just apply p.use_smooth to the ones on the curved surfaces! Since I'm creating them programmatically, I can do something like for i, p in enumerate(ob.data.polygons): if not i in [9, 23, 24, 25]: p.use_smooth = True but nicer of course. I"ll adjust the question again - this is a perfect answer. Thanks! $\endgroup$
    – uhoh
    Nov 1 '16 at 10:48
  • 1
    $\begingroup$ Yes, that will be the best solution. I will add this to the answer completeness later. My solution is a more generic approach, since I wasn't sure if you would use this for other objects as well. $\endgroup$
    – Leander
    Nov 1 '16 at 11:15

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.