What’s a Klein Bottle?

Klein Bottle (3D)

A Klein Bottle can be thought of as a 3D Möbius strip, a surface with no interior that produces a shape that looks like an odd bottle. I don’t claim to be an expert at generating such things, but Paul Bourke is and you can read about it (and loads of other cool shapes) in more detail on his site.

Generating geometry in Houdini Python

While it seems possible to generate geometry in Vex, I decided to see how to do it with Python as it gives me an excuse to dabble in the Houdini Python API and I think it fits this type of project better. The bible for anything Houdini Python is the documentation itself, so I started looking at the examples there.

The main thing I discovered was that you can only generate geometry is limited to the Python SOP context, so a regular Python node will not work. You will need to make a new node using File >> New Operator Type >> Python Type, then set the Network Type to Geometry Operator.

Once all that’s set up it’s very easy to create geometry, simply use something like:

node = hou.pwd()
geo = node.geometry()
 
poly = geo.createPolygon()
 
p0 = geo.createPoint()
p0.setPosition( [0,1,0] )
p1 = geo.createPoint()
p1.setPosition( [1,1,0] )
p2 = geo.createPoint()
p2.setPosition( [1,0,0] )
p3 = geo.createPoint()
p3.setPosition( [0,0,0] )
 
poly.addVertex(p0)
poly.addVertex(p1)
poly.addVertex(p2)
poly.addVertex(p3)

Although I had to write some extra code to generate polygons properly, generating the points of the Klein was easy to do in a loop and pretty fast until I set it to high point counts.

Adding attributes to new points

The only other issue I had was adding attributes to points etc, I got errors related to the attribute not existing on the point. I eventually found an (obvious in hindsight) solution to this, you simply have to add the attribute to the geometry first and then you can set the value on the point:

nrmAttrib = geo.addAttrib(hou.attribType.Point, "N", (0.0, 0.0, 0.0))
 
for i in range(0, N):
    for j in range(0, N):
        u = umin + i * (umax - umin) / float(N)
        v = vmin + j * (vmax - vmin) / float(N)
        p = eval(u,v)
 
        p0 = geo.createPoint()
        p0.setPosition( p )
        p0.setAttribValue(nrmAttrib, calcNormal( eval(u, v), eval(u + delta, v), eval(u, v + delta)) )

The result

Here’s the final Klein geometry rendered out in Mantra with a glass shader, it’s missing a section because of the way I’m generating faces for it and I lack the time to debug it, but I think it makes it more unique than the generic klein bottle anyway.

klein

Bonus: Using it to test out my Reaction Diffusion (with a laplacian based on connected topology)