A 3D spoon


I have pasted some code at the end of that post. If you put it in a file called macro.gmic, you’d be able to redo the commands proposed in this post that call such a file.


I have been in a museum lately, it was great and at some point, I saw a spoon, a spoon that was designed more to be beautiful than useful (see image below).

Spoon designed by Isaie Bloch

Spoon designed by Isaie Bloch

I thought that keeping aside aesthetic considerations, such a spoon was just a conventional spoon with some material subtracted from the handle using a random pattern. I thought I could try to do something like that. I just have to create a 3D shape and send it to a 3D printing web site and I would have my spoon.

3D vectors images in G’mic

G’mic easily handles 3D images when they are 3D raster images (also called volumetric files), i.e. matrices full of voxels. But to print in 3D, you need to provide a 3D mesh, i.e. a 3D vector representation of your shape.

Limited 3D objects manipulation

G’mic capabilities in such 3D objects (as it is referred in the documentation) are very limited. As some expert stated it: “G’MIC is not really meant to *process* 3d objects”. You are nowhere close to what Blender can do. It has a marching cube algorithm (command -isosurface3d), it can “elevate” some 2D surface (-elevation3d) or it can create simple shapes (-sphere3d, -box3d, …), not much more. For example, it doesn’t have any boolean operator, so I can already forget about that material subtraction in G’mic.

A rare format

Another difficulty is that G’mic handles only one 3D object format: the quite unused OFF format. A standard format for 3D printing would rather be the STL.

After some research, I was unable to find any scriptable way to convert OFF in STL and reverse. The most handy way to do that is meshlab, which isn’t scriptable and doesn’t allow any boolean operation. Neither Blender(for artists) nor Salome(for techies) are able to handle the OFF format. They both have a python API, but tests proved me that writing an OFF reader/writer is painful, learning Blender is painful, it is impossible to call the python API from outside Blender and it is painful to do it from outside Salome, which is also painful to learn and install and handles STL imperfectly.

The good news is that if Shapeways doesn’t accept the OFF, Sculpteo does. So at the end of everything, I’ll save a few clicks by sending my file to them.

Strategic conclusion

So, if I want to use G’mic to create my random pattern, I’ll have to stay with G’mic until the end or I have to add numerous clics in my process, many of them being painful. And I want to create my pattern in G’mic. And I am interested to see until where I can go in 3D printing with G’mic.

So, I abandon the pattern substraction, my random shape will be made with addition. I don’t really need some boolean operator for my addition, as I realized that I just have to create 2 overlapping shapes, put them in my OFF file and Sculpteo would handle that just fine, it will be one single plastic thing at the end.

Ok, ok, let’s go!

Starting from a conventional spoon

I found a conventional spoon (thank you Hobbyman), I downloaded it, I removed the handle painfully thanks to Blender, meshlab that to an OFF file. And then I was ready for thousands of tests.

Now I have a spoon bowl!

Now I have a spoon bowl!

Random pattern

I wanted my random pattern to come from the -stencil command because I like it.

CC-BY stencil command on a cow: gmic cow.jpg -to_gray -stencil 2,1,10

CC-BY Emilio Labrador
stencil command on a cow: gmic cow.jpg -to_gray -stencil 2,1,10

I needed it to be seamless since it is intended to roll and that both ends must match nicely. For that, I duplicate some random noise so that the -stencil command run on it sees the same noise on each side. I am so proud of that trick.

gmic 200,200 -rand 0,255 [0] -a x -stencil 4 -crop 25%,75%

gmic 200,200 -rand 0,255 [0] -a x -stencil 4 -crop 25%,75%

Actually, as I wanted to have smooth edges, I added some -blur in the process.

Earning the third D

Now that I have the texture, I have to make it 3D. I tried to use the -elevate command, that transforms 2D image in 3D volumetric files. The idea was to do everything with volumetric files and to pass to 3D objects only at the end with -isosurface3d. but whatever I did, the final result looked always too pixelized.

So, I used the -elevation3d command to get directly a 3D object.

gmic macro.gmic -seamless_stencil 100,200,2 -elevation3d 0.1

gmic macro.gmic -seamless_stencil 100,200,2 -elevation3d 0.1

But this means that, even if G’mic isn’t meant to, I now have to *process* a 3D object.


For example, I have to roll the texture to get a round stick that is supposed to be a spoon handle at the end. Even if this is not convenient, everything is explained in the wiki: the -split3d command transform the 3D object into 6 column vectors which contain all the informations that constitute it. For example, here, the idea is simply to modify vertices coordinates to go from flat to round. For that, you have to play with the third column vector, the one that contains vertices coordinates. Some -sin and -cos do the trick. I made a generic custom command for that : -roll3d.

gmic macro.gmic -seamless_stencil 100,200,2 -elevation3d 0.1 -roll3d 100 -*3d 1,5,1

gmic macro.gmic -seamless_stencil 100,200,2 -elevation3d 0.1 -roll3d 100 -*3d 1,5,1

Sewing and closing

My 3D mesh will only mean something to a 3D printer if it is a closed surface. This means that I have to close the bottom and the top of the stick, but I also have to sew it along its length.
By sewing, I mean modifying the triangles from one side to have them use the vertices of the triangles from the other side. This can be done by manipulating the fourth column vector.
To close the bottom and the top, I choose to add some triangles at both ends. All those new triangles use a vertex created on the stick axis and already existing vertices from the triangles at the ends. This requires the manipulation of almost every column vector and it was a nightmare to have it work. I made a not so generic custom command for all that called -close_tube3d.


Spoon completion

I only have a handle so far. I need to make a single OFF file with the handle I just made and the bowl I stole from Hobbyman. The good news is that it is trivial: just add the two 3D objects with the command -add3d (shortcut -+3d). Well I also had to move the handle and the bowl around so that I get a good spoon at the end.


Glorious conclusion

Now I have a spoon! and since I chose a white plastic, I can even eat with it. OK, it isn’t as beautiful as Isaie Bloch’s one, but my children like it.

Actually, I printed two of them, one in polished plastic to see the difference. Well, there isn’t much difference, they both give a granular feeling in the mouth. My children have tested, they are quite solid, not stiff at all, but you can give them back their shape without breaking them. The handle ends are a bit sharp, you can not cut anything with it, but it makes it a bit uncomfortable in the mouth, I could have done something about it, but I was fed up with pain, I wanted my spoon IRL at once. I doubt I will redo any spoon in the future, but it gave me some ideas for other things.

gmic macro.gmic -handle_and_spoon

gmic macro.gmic -handle_and_spoon

The code

  -stencil_tube3d 50,100,50 -*3d 0.04,0.13,0.04
  -c3d -rotate3d[0] 0,0,1,90
  -+3d[0] -47
  -+3d -rotate3d 1,0,0,180

# gmic macro.gmic -stencil_tube3d 100,200,100
#$1 : nb segments
#$2 : nb segments longitudinal
#$3 : radius
  -seamless_stencil $1,$2,2 
  -elevation3d 0.2 -roll3d $3 
  -*3d 1,5,1 
  -close_tube3d $1,$2

# gmic macro.gmic -seamless_stencil 10,200,2 -elevation3d 0.1 -roll3d 100 -*3d 1,5,1 -close_tube3d 10,200
  -color3d 255,255,255  #I want only one color
  -split3d 1            #require version or more
  #sew tube longitudinally
  -e LONGI
      -s y
      -e {5*($1-1)-1}
      --[{5*($1-1)-2}--1:{5*($1-1)}] {$1-1}
      --[{5*($1-1)-1}--1:{5*($1-1)}] {$1-1}
      -a y
  #close tube at lower end:
  -e LOWER
    (1;{$1-1}) -+[1,-1]                         #increment vertices and primitive number
    (0;$ymin;0) -a[2,-1] y                      #add a vertice in vertices data
    #add triangles in primitive properties: 
    -i 1,{$1-1},1,1,3
    -i 1,{$1-1},1,1,y
    --shift[-1] 0,1,0,0,2
    -i 1,{$1-1},1,1,{@{1,(0,0,0,0)}-1}
    -a[-4--1] x -r[-1] 1,{w*h},1,1,-1
    -a[3,-1] y
    -i 1,{{$1-1}*3},1,1,255 -a[4,-1] y          #new triangles are white
    -i 1,{$1-1},1,1,1 -a[5,-1] y                #new triangles opacity = 1
  #close tube at upper end:
  -e UPPER
    (1;{$1-1}) -+[1,-1]                         #increment vertices and primitive number
    (0;$ymax;0) -a[2,-1] y                      #add a vertice in vertices data
    #add triangles in primitive properties: 
    -i 1,{$1-1},1,1,3
    -i 1,{$1-1},1,1,y+{$1*($2-1)}
    --shift[-1] 0,1,0,0,2
    -i 1,{$1-1},1,1,{@{1,(0,0,0,0)}-1}
    -a[-4--1] x -r[-1] 1,{w*h},1,1,-1
    -a[3,-1] y
    -i 1,{{$1-1}*3},1,1,255 -a[4,-1] y          #new triangles are white
    -i 1,{$1-1},1,1,1 -a[5,-1] y                #new triangles opacity = 1
  #back to 3d object
  -a y

# gmic macro.gmic -seamless_stencil 200,200,2
seamless_stencil: -skip ${3=0}
  $1,$2 -rand 0,255 [0] -a x    #random pattern repeated twice
  -stencil 1                    #stencil
  -blur $3                      #blur has to be done before cropping to ensure seamless
  -crop 25%,75%                 #keep only the middle

# gmic macro.gmic 200,200 -rand 0,255 --mirror x -a x -stencil 1 -blur 2 -elevation3d 0.1 -roll3d 100 -*3d 1,5,1 
# $1 : radius
  -split3d -local[2]
    -r 3,33.3333333333%,1,1,-1
    -s x
    -+[-1] $1                     #radius of future vertices
    --*[0] {2*pi/$L} [-1]
    -cos[-2] -sin[-1]
    -*[-2,-1] [-3]
    -mv[1] 0
    -a x
    -r 1,300%,1,1,-1
  -a y

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s