1
$\begingroup$

I've asked this elsewhere but have not got a solution yet. The image below show's what I am trying to achieve in Blender but I'm not sure if any of its built-in tools or addons can replicate this workflow. The suggestion's I've been given result in inaccurate geometry and I'm seeking a solution as per the below image.

enter image description here

$\endgroup$
  • $\begingroup$ I would do this shape with curve Geometry+Taper, or Array+Curve+MeshDeform modifiers, but I guess it doesn't answer your question $\endgroup$ – moonboots Oct 30 '18 at 13:10
3
$\begingroup$

Using Follow path constraint offset

enter image description here

  • Add a flat profile mesh on the xy plane, give it a follow path constraint of -Z forward (face normal pointing out) and y up.
  • Set to fixed position. One end of curve will be 0 and the other 1. Duplicate the profile mesh and move to another offset on curve.
  • Scale either end or both. With both end profiles selected run the script below.
  • "Extrudes" segments time around the curve linearly interpolationg from start scale to end scale. Makes a mesh object using the global coordinates of the arranged profile.

EDIT: Update for 2.8x

The script:

import bpy
import bmesh
from mathutils import Vector, Matrix

context = bpy.context
scene = context.scene
dg = context.evaluated_depsgraph_get()
coll = context.collection or scene.collection


def offset(ob):
    return ob.constraints["Follow Path"].offset_factor


ob1, ob2 = sorted(context.selected_objects, key=lambda o: offset(o))
T = ob2.matrix_basis @ ob1.matrix_basis.inverted_safe()
ml2 = ob2.matrix_basis.copy()
start = offset(ob1)
end = offset(ob2)
segments = 10
d_offset = (end - start) / segments
me1 = ob1.data
me = me1.copy()
bm = bmesh.new()
bm.from_mesh(me)
# remove non boundary edges
#bmesh.ops.delete(bm, geom=[e for e in bm.edges if not e.is_boundary and e.link_faces], context='EDGES')
bm.to_mesh(me)
bm.clear()
# build the mesh by sliding ob2


def ring_fill(ring1, ring2):
    for e1, e2 in zip(ring1, ring2):
        bm.faces.new(e1.verts[:] + e2.verts[:][::-1])


bm.from_object(ob1, dg)
bmesh.ops.transform(bm, verts=bm.verts, matrix=ob1.matrix_world)
offset = start  # + d_offset
copy = ob2
copy.data = me
scale2 = ob2.scale.copy()
nring = len(me.vertices)
ring = [e for e in bm.edges if e.is_boundary]

for i in range(segments):
    offset += d_offset
    copy.constraints["Follow Path"].offset_factor = offset
    copy.scale = ob1.scale.lerp(scale2, (offset - start) / (end - start))
    dg.update()
    bm.from_object(copy, dg)
    bmesh.ops.transform(bm, verts=bm.verts[-nring:], matrix=copy.matrix_world)
    next = bm.edges[-len(ring):]
    ring_fill(ring, next)
    ring = next

# reinstate the end (much of the same)
ob2.data = me1
ob2.matrix_basis = ml2
dg.update()
bm.from_object(ob2, dg)
bmesh.ops.transform(bm,
                    verts=bm.verts[-len(me1.vertices):],
                    matrix=copy.matrix_world)
next = [e for e in bm.edges[-len(me1.edges):] if e.is_boundary]
# fill
ring_fill(next, ring)
# recalc normals
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=1e-7)
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
ob1.select_set(False)
ob2.select_set(False)
# make new object and link to scene.
ext = bpy.data.meshes.new("Extrusion")
bm.to_mesh(ext)
extrude = bpy.data.objects.new("Wall", ext)
extrude.show_wire = True
extrude.show_all_edges = True
coll.objects.link(extrude)
$\endgroup$
  • $\begingroup$ a better fill, because it's lower-level? $\endgroup$ – Robin Betts Nov 9 '18 at 19:14
  • 1
    $\begingroup$ The ring_fill method as opposed to the bridge loops bmesh operator. It's quicker and doesn't require the inputs to be loops. $\endgroup$ – batFINGER Nov 10 '18 at 1:07
2
$\begingroup$

If you are looking for an identical workflow, I guess you'd need to have it coded as an addon.

If you just look for a clean result:

I would use an ordinary mesh and a curve modifier.

Model the wall without the curve, you could use the bridge tool for that. I positioned the object origin where the curve will be.

enter image description here

Then build the curve so that it's origin sits at the start of the curve.

Place both object origins on top of eachother and make sure their local axes point in the same direction.

After that, give the mesh a Curve Modifier using the curve in question.You might need to switch direction in order to get a good result. With curve modifiers it's all about axes, where the object origins are and the direction of the curve. If that's in alignment, all's well.

And you can change the mesh. You don't have to stick to simple forms.

The result looks pretty similar.

I have put a simple subsurf modifier before the curve modifier to increase resolution. Creates a bit of excess verts though.

enter image description here

$\endgroup$
  • $\begingroup$ Hey, thanks for the reply. It would be nice it there was a solution as simple as I had shown but I'm happy to work with Blender workflow if it creates the correct geometry. In your example, is the wall a flat plane or does it have depth as well? $\endgroup$ – SmartSolid Oct 30 '18 at 15:55
  • $\begingroup$ you can add depth with a Solidify modifier $\endgroup$ – moonboots Oct 30 '18 at 16:17
  • $\begingroup$ Yeah I'm aware of that but it didn't mention it in the workflow if one was used or not and if it was, at which point in the process is it applied e.g. prior to the curve modifier, at the very end? etc... $\endgroup$ – SmartSolid Oct 30 '18 at 16:25
  • $\begingroup$ at the bottom of the modifier stack $\endgroup$ – moonboots Oct 30 '18 at 16:32
  • $\begingroup$ I actually used a cube and scaled it in editmode. Or I use a plane and duplicate it. $\endgroup$ – Haunt_House Oct 30 '18 at 16:43

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.