How to make crystal like shapes with Processing?

Hi @liukov, welcome to the forum.

There are probably many ways to produce that kind of shape but I think your approach (applying modifications to a PShape object) is quite relevant in this case.

My first thought was to suggest playing with HemeshGui. It’s a visual tool built on the Hemesh library that facilitate the creation and manipulation of polygonal meshes. For instance you could start with a box, elongate it with the skew ‘modifier’ and then chamfer the corners.

I then realized you could get more realistic results with a simpler approach I tried some time go and which is based on this blogpost. Basically all you would have to do is noising the vertices of an icosahedron. The key part is to divide the normalized vertices locations (PVectors) by the noise value instead of multiplying them.

The simplest way to do this is to use the Hemesh library I mentionned above.

  • create an icosahedron with the creator class
  • normalize the vertices
  • compute a 3D noise value based their locations (x, y and z)
  • divide the (normalized) vertices by their corresponding noise value

Normally this should result in long, sharp spikes in the mesh:

Short example sketch with Python mode:

add_library('peasycam')
add_library('hemesh')

factor = 1.5

def setup():
    size(1000, 600, P3D)
    smooth(8)
           
    creator = HEC_Geodesic()
    creator.setType(WB_Geodesic.Type.OCTAHEDRON).setRadius(200).setB(12).setC(12)

    global mesh, render
    mesh = HE_Mesh(creator)
    render = WB_Render(this)
    cam = PeasyCam(this, 800)
    
    for i, v in enumerate(mesh.getVertices()):
        p = PVector(v.xf(), v.yf(), v.zf()).normalize().mult(1.1) ### --> Converting to PVector() for clarity but could use normalizeSelf(), scaleSelf() or mul() instead
        n = map(noise(p.x * factor + 1, p.y * factor + 2, p.z * factor + 3), 0, 1, -.004, .03)
        p.div(n)
        mesh.getVertex(i).set(WB_Point(p.x, p.y, p.z))

def draw():
    background('#DCDCDC')
    lights()
    
    render.drawFaces(mesh)

Because of the pseudo-random nature of Perlin noise you’ll never end-up with the same result so feel free to run sketch as many times as you like until you find an output you feel satisfied with.

If realism is important to you, you can go a step further and render your mesh with a third party software. Here’s an example of a mesh generated with the same sketch and then rendered with Keyshot:

(Note that If you have a windows/linux machine you could also try @kosowski’s simplePBR library within your Processing sketch)

11 Likes