13
$\begingroup$

I'd like to model a surface like this curved funnel (pic from Wolfram Math World):

enter image description here

So far I've tried starting with a cone, subdividing it and scaling down successive rings of vertices, but it's a bit fiddly and the result wasn't great. Ideally I'd like a solution which doesn't involve too much vertex selection, so that I can implement it via the API.

Can anyone think of a better way?

$\endgroup$
10
$\begingroup$

Try using the Extra Objects addon, with its XYZ Math Surface mesh option!

Use the parametric equations with a = 5, say:

The "Add X,Y,Z Function Surface" options with x = u cos(v), y = u sin(v), and z = 5 log(u + 1)

Note that I use log(u + 1) instead of just log(u), because the domain of u includes zero.

Then invert the normals, shade smooth, and you'll get

Rendered funnel

(To enable this addon, go to FileUser Preferences, select Add-ons, search for "Extra objects," and enable the "mesh" one. Then, to create the object, hit ShiftA and select Math SurfaceXYZ Math Surface.)

$\endgroup$
  • $\begingroup$ Note that I suggest this because it gives you all of the precision of the Python solution, with the advantage of already having been implemented, tested, and tweakable! $\endgroup$ – wchargin Dec 19 '16 at 3:19
  • $\begingroup$ Thanks, I like this solution. Using the same equations, I ended up with a curved funnel inside a cone. I had to delete the faces that made up the cone before flipping the remaining normals. $\endgroup$ – user2950747 Dec 19 '16 at 7:57
  • 1
    $\begingroup$ @user2950747 Make sure to leave "U wrap" unchecked (see screenshot). $\endgroup$ – wchargin Dec 19 '16 at 17:06
12
$\begingroup$

You could make a bent line in the XY plane for example (1), a subdivision surface modifier and use a screw modifier (2) with

  • screw : 0
  • steps : as you like
  • angle : 360

(1) enter image description here

(2) enter image description here

$\endgroup$
9
$\begingroup$

I would use the formula directly in python. It is the better approach to not use operator, but rather "absolute" calculations when creating objects in python.

Here is a rather messy mockup code for the funnel.

import bpy, math, bmesh
import numpy as np

def create_new_mesh(name = "myObj"):
    me = bpy.data.meshes.new(name + "_GEO")
    ob = bpy.data.objects.new(name, me)
    scn = bpy.context.scene
    scn.objects.link(ob)
    scn.objects.active = ob
    ob.select = True
    ob.show_name = True
    return ob, me

def funnel_vert_at(x, y, a = 1):
    p = float(x**2+y**2)
    return 0.5 * a * np.log(p)

def funnel_iteration(iteration_start, iteration_end, iteration_steps, i, exp = 8):
    i_s = iteration_start**(1/exp)
    i_e = iteration_end**(1/exp)
    iteration_step = (i_e - i_s)/(iteration_steps-1)
    return (iteration_step * i + i_s)**exp

def create_funnel_loops(iteration_start = 0.1, iteration_end = 1, iteration_steps = 9,rotation_steps = 24, iteration_exp = 8, a = 1):
    verts = []
    for i in range(0, iteration_steps):
        for s in range(0, rotation_steps):
            rad = math.pi*2 / rotation_steps * s
            dist = funnel_iteration(iteration_start, iteration_end, iteration_steps, i, iteration_exp)
            print(i, dist)
            x = math.sin(rad) * dist
            y = math.cos(rad) * dist
            verts.append((x, y, funnel_vert_at(x, y, a)))

    edges = []
    for a in range(0, iteration_steps):
        for b in range(0, rotation_steps):
            next = 1
            if b is rotation_steps - 1:
                next = -b
            b = b + a*rotation_steps
            edges.append([b, b + next])
    return verts, edges



me = create_new_mesh("Funnel")[1]


verts, edges = create_funnel_loops(
    iteration_start = 0.1,
    iteration_end = 1,
    iteration_steps = 7,
    rotation_steps = 9,
    iteration_exp = 8,
    a = 1
    )

me.from_pydata(verts, edges, [])
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.bridge_edge_loops()
bpy.ops.object.mode_set(mode='OBJECT')

The main formula is in the function funnel_vert_at(). X and Y are created in create_funnel_loops with the circle functions sin and cos.
Since I was too lazy to implement it, the script uses the internal Bridge Edge Loops function, in the final solution, the faces should be calculated as well.

I also calculated the funnel_iterations very roughly with the power function. You should reverse the funnel formula so that the spacing between the loops is more even.

enter image description here

$\endgroup$
6
$\begingroup$

It is also possible to bevel a Curve (I used a path here, just because it's a straight line by default) and use a second Curve as an Taper Object which gives the desired shape:

enter image description here

The advantage of this method is that the shape stays editable (non-destructive)

enter image description here

When you're done, you can convert it with ALT+C from Curve to Mesh afterwards.

Also see this great answer

$\endgroup$

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.