14
$\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$
0

4 Answers 4

12
$\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$
3
  • $\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, 2016 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$ Dec 19, 2016 at 7:57
  • 1
    $\begingroup$ @user2950747 Make sure to leave "U wrap" unchecked (see screenshot). $\endgroup$
    – wchargin
    Dec 19, 2016 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$

You must log in to answer this question.

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