Alik Kadoum spoke in detail about three methods of surface modification of objects for SLS printing, which he applied while working on a project of the Austrian sculptor Oliver Laric.
Hello. My name is Alik Kadoum. I live in Odessa, Ukraine. I have been doing 3D graphics for over seven years. I could never choose for myself any single narrow specialization: everything was interesting. Well, apart from the interior design. So, I am kind of a couture guitarist. Computer graphics first interested me in my first year at the Architecture Academy, (here is a place for your jokes about interior design and sofas from stocks). I knew how to draw a little, but I learned academic drawing, composition, and painting already at the academy. I cannot say that I loved playing video games, however, I was terribly interested in watching developer diaries or movies about films. I was incredibly fascinated by the process of creating something.
And then one day, a good friend of mine, a programmer invited me to an indie game studio. It turned out that programmers alone cannot make a game and they needed a concept artist and a font designer (how fortunate that at the academy, among other things, we made fonts by hand). Acquaintance with computer graphics began with the creation of textures for models of medieval armor, helmets, weapons ... I did old-school painting in Photoshop. After, I reworked these models in 3Ds Max.
Later, I met with ZBrush, we fell in love forever. And with that, I got the first graphic tablet, which is unforgettable as the first kiss. I met my future colleagues in a strange accident. They came to advise us on motion capture and filming. I got interested and moved on to them. This is how I ended up at Pixelated Realities, where I’m still working.
Our main activity is directly related to photogrammetry and 3D scanning. We are working in many areas: games, movies, AR/VR. But now most of the time is spent on digital fabrication based on scanned data. Over the past 5-6 years 80% of my work has been related to the processing of raw scans, mainly cultural and architectural monuments.
But enough of that. Let's get down to business.
Almost every artist should feel the taste of the freelance sooner or later. The same thing happened to me. It was difficult to monitor different platforms in search of clients. Also, it took a lot of time. But one day I saw a job in which it was necessary to modify the surface of objects with the pattern below, as well as a certain hole diameter and distance between them, all for SLS printing in industrial sizes.
Suddenly, the client was sculptor Oliver Laric, creator of threedscans.com. This is a project that I admired in the early months of my acquaintance with photogrammetry. The site has collected and posted many famous scans of sculptures from around the world in free access. I strongly recommend visiting the site, over there you can see many models that are familiar to you from tutorials, articles, and clips. And how interesting it turned out that I need to work with scans of famous cultural monuments!
By the way, after this project, my colleagues nicknamed me "professor-perforator". I think you can guess why.
My pipeline has changed quite a lot and is still changing. I will tell you about it in order. Even rather about its evolution. Anything here is the only true or super correct, but perhaps some techniques can help someone in solving their problems. Let's start!
The first pipeline was based on using a texture with the required ratio of the diameter of the holes to the distance between them. The main challenge was to maintain printability for such a complex object. Therefore, the first idea to make holes on the outer surface and just add thickness to it immediately disappeared.
And the curvature of the surface does not allow the pattern to be distributed as evenly as I would do in any CAD with more even surfaces. I decided to subtract cylinders from a fabrication-ready model. To do this you need to prepare a model without destroying those already made design decisions. At first, it was necessary to leave only the outer surface, separating the thickness and structural grooves from it. After that, for convenience and ease, I decided to make remesh in ZBrush.
Later, you should unfold the model with minimal distortion so that the texture has no stretching because further, we will try to make geometry out of it. RizomUV helped me to get rid of distortion. In my opinion, this is the best tool for creating UVs.
Earlier, I had an interesting project where I needed to unfold the dome of one historical monument for scientific documentation, in order to calculate the surface areas and transfer them to the drawings. So, it wasn’t difficult for me to unwrap a model of a real physical object. Please note that my methods are quite different from those of game development or cinema when it comes to any kind of fabrication, despite the use of the same tools.
I created a texture in Photoshop with the required proportions and applied it to the model.
The result was something like this:
Things got more interesting: I had to figure out how I could turn it all into geometry. Sure, Modo is a great tool for me, but I couldn't figure out how to implement it here. ZBrush surprisingly immediately prompted me to use Noise on UV and convert it to mask. Not perfect, but already something. Of course, you can easily mess up with the scale here, so I did a "crutch": I created three cylinders of the required diameter and distance between them, inserted them perpendicular to the model, and scaled Noise until I got the right scale. I made several levels of SubDivide before. Since we want to get a clean mask, it is important to set the following parameters to zero: Noise Scale, Magnify by Mask, and Mix Basic Noise.
After several manipulations I’ve got the right scale:
Press Mask by Noise:
Got the following:
It's not hard to guess what to do next. Add masked areas to one polygroup and delete everything we don't need. We get an interesting surface, which is still far from final:
As we can see, it seems like circles, but it seems like not. Sure, it would be possible to make Polish by Groups, but the disadvantage of this method is that it does not allow you to correctly preserve the orientation of these circles, and the radius can be different for everyone.
So, then I go to Modo to process them with the Radial Align Tool. Before that I removed all internal edges, except for the contour, to get N-gon. With this tool, you can set the radius of the circles, so I will already be quite close to the desired one. You can also specify the number of sides of the circles if needed. For example, when the hole diameter was 2 mm, 12 sides were enough. With a radius of 3 mm, I increase the number of sides to 16. Then, after SLS-printing there’s no visible angularity.
Now everything is obvious: extrude circles by the required distance to get the cylinders and return to ZBrush. I use the wonderful tool called Live Boolean for preview. If necessary, I go back to Modo to correct or rotate some cylinders and back to ZBrush. When everything is fixed, I make the final Boolean and I throw Decimate on top if needed.
Exporting in .stl and we’re done!
The first method seemed to give the desired result, but my inner perfectionist was on fire. I was terribly annoyed by the dependence on the density of the mesh, the curve geometry, no regularity, a lot of manual edits. And the processes themselves look fast in pictures, but in fact, we had to work with meshes around 20-40 million polygons to get more accurate results, and this, believe me, is a burden. Since there were several dozens of models, I realized that a procedural approach would save my life. But at that time, I had never even tried Houdini.
I decided to make a pattern generation tool with the ability to set the radius and distance whenever I want. Immediately I began to think about how to make a non-destructive scheme without creating movement by hand, as this will help change the diameter in the future. I jumped into Modo Schematic, and, using the trigonometry that I taught at school, I built the movement with the basic nodes. I will try to explain what we have from trigonometry. In fact, our pattern is an ordinary hexagon. A circle is inscribed in each cell. This is how it looks like:
Long story short: 3 contiguous hexagons, a circle is inscribed in each, respectively, the center of each hexagon is the same as the center of each circle; the distance between the centers is known from the task, (3 radii of the circle); we have an equilateral triangle ABC, it’s height h (CD) is the offset of the circle along the Y-axis, and half the distance between points A and B is the offset along the X-axis.
By the way, check this out.
Since we also have a right triangle ADC, using the definition of sine, we can calculate the offset we need along Y-axis, i.e., sin 60 x 3R; and along the X-axis - 1.5 x R.
Next, I created a procedural cylinder with a Z value of 0 to make a circle, and I linked the Y and X radius. Later I added the Clone operator, pulled the Linear Generator from the Tool Pipe, and added it to the Schematic. Sprinkle with an elementary mathematical operation of multiplication, fill it with a sine of 60 degrees, and set it to Offset X and Y until ready. We’ve got the following:
And this happens in the viewport:
Nice! The pattern is almost done. It remains to add an Array, feed it the Offset values for X and Y. Put 3 radii to X, and 2 heights to Y, which we got from the first calculations. And boom, here we go:
You can add a couple of handles for convenience, but this is cosmetics. After all these manipulations, my tool looks something like this:
Now we need to apply it to the model in some way. The only thing that came to my mind was to make a UV mapping and project the resulting pattern. Modo has a great UV Transform tool. Let’s dive into it.
Our new model is much less obvious. Its surface curvature is incredibly complex. Unfortunately, here we will have seams since you won’t be able to unfold it to one UV island.
Primarily I isolated the outer surface, just like in the first pipeline. Unwrapped it in RizomUV Real Space, which is just designed for real objects – fabrication or laser cutting. As you can see, there is some distortion, but I found the distortion on the face to be better than the seam around the nose. I tried to put the seams in places of occlusion and at the peaks of curvature. Got this:
Go back to Modo, import our unwrapped mesh. Next click Texture/Convert UVs To Mesh. We’re doing this to see our borders.
After that, take out the generator we created earlier and using Array Count X and Y we increase our pattern until we cover our entire UV with a margin. We shouldn’t worry about the scale, since Rizom RS made UVs in real physical dimensions.
I decreased the side count of the circle to 6 just for optimization and performance. We need them only for coordinates, not for extrusion.
Next, freeze our circles (Right Click/Freeze Operations/Freeze), select them, add the UV Transform operator: as Target Mesh select our mesh with UV mapping, and as Target UV Map – its UV, which is called Texture by default. Click OK and wait.
We got this:
Yes, there were small artifacts that I decided to turn into an interesting art object, but these are just little things, they are easy to remove by hand. The best way to avoid artifacts is to crop the circles by the UV with a slight offset inward before doing the UV Transform. But I was in rush, doing it by hand was faster and clearer for testing purposes.
Now let’s create a cylinder, I made it procedurally, with a radius of 1mm, and a height as needed to fully penetrate the original model. I throw the cylinder into Schematic, throw the new geometry after UV Transform there too. Add the Replicator node, select Use Polygons in the Instancing parameter so that the cylinders are placed not by points, but by our n-gons. Connect the cylinder to Prototypes and the circles to Particle Source. Like this:
To avoid obvious intersections on the inner surface, I added a second cylinder, or rather a truncated cone (in fact, a circle with an extrude and a bevel). It is important here that the inner radius shouldn’t be very small, to prevent printing errors, because it is a very expensive pleasure. In my case, I made an inner radius of 0.7mm. I decided not to go below. Made a second Replicator node, a second mesh container for the circles, and another container for potential cylinders. All this was inserted into the Merge Meshes node.
Now you can edit the seams (yes, by hand) and turn the cylinders slightly in especially curved or narrow places or replace them with truncated cones.
Nice looking, now make a Freeze operation, export, and go to ZBrush for preview. Go back and forth to fix something if needed. The final result looks like this:
Now let's move on to the last pipeline that I was able to reach. At the moment for me, it is the most optimal, fastest, and most natural. I have consulted a lot on forums, chats, and YouTube comments. Most often, I heard the opinion: “It can definitely be done in Houdini, I don’t know it, but it is definitely possible!!!”.
I was afraid for a long time, but several kind people on the Internet were able to convince me, for what I am grateful to them. I dived at Houdini, trying to learn the interface or some of its basic things, philosophy. But when your deadlines are on fire, everything is on fire, you are on fire and you need to work urgently, then there is no time for training. Learned how to rotate the viewport? Ok, you can work. Moreover, there is an unspoken rule: "If it cannot be done in Houdini, it cannot be done anywhere else."
I studied terabytes of YouTube, dozens of articles, asked a lot of questions and seems to find a suitable tool for my tasks. The first thing I had to embrace as an architect and artist was the Platonic solids. Take, for example, a standard soccer ball with black patches. It is nothing more than a truncated icosahedron. Even such a seemingly elementary form as a sphere cannot be built with only hexagons – the geometry will resist.
It’s important for your personal inner perfectionist. Just. Embrace. It.
Here’s an extremely useful video explaining what Platonic Solids are:
We won’t go into the basics of Houdini, let's get straight to the magic. In the beginning, we have an even more complex model:
Already according to the principle, we know, we separate the outer surface from everything else. I could do it procedurally, grouping by angle, normals, etc., but unfortunately, the models are different, and it doesn’t always work as it should. It is often much faster and easier to separate it with your hands.
The hole diameter in this model is 3mm, the distance between the holes is 1 radius - 1.5mm. The proportions are the same. Unfortunately, I did not find a convenient method for specifying the distance between the holes: I had to think from the other side.
Before going further let’s do a quick test that can explain the magic and the idea. Take a simple Sphere node with Primitive type - Polygon and Frequency parameter about 6. We’ll try to create a pattern on it. Let’s drop a Scatter node with Relax Iterations parameter set to zero. We can see 1000 point with a random position on the sphere. But here’s the trick: as long as you push further Relax Iterations the points start to regularize. Logically, the only method to relax some points is to make distance equal between each neighbor. This only can make 6 equidistant neighbors around 1 point. Or even more simple: if we take the minimum number of points to be equidistant, I mean 3, we’ve got an equilateral triangle. The hexagon, fortunately, consists of 6 equilateral triangles.
Let’s make it clearer. Take a Circle node and a Copy to the Points node. Put the Scatter and the Circle nodes into Copy to Points. Boom! Nice pattern with no seams. Imagine how this would be if I did it with the previous pipeline…
After this, I got the idea that the Force Total Count parameter in the Scatter node can help me to deal with distances. So, we need to figure out how to get this count.
I thought about the areas. Or rather, the area of the surface that needs to be covered, and the area of the hexagon into which the circle needs to be inscribed. If we relate the surface area to the area of one hexagon, then we will get the number of these hexagons, which means the number of holes.
Let’s get back to our trigonometry:
We still have the same hexagon. To build it procedurally, you need to understand its dependencies on the hole. We already know the height h from previous calculations. According to the same definition of sine, we can find the length OM that we need, which is the radius of the hex itself.
Let's build a circle and this hexagon in Houdini. Take two Circle nodes: in the first, we set the radius we need and Divisions parameter to 12. To link the radius along X and Y, we do Right Click/Copy Parameter on the radius parameter along X, and Right Click/Paste Relative Reference in the Y parameter:
After that, in the second Circle node, we do the same, only the Divisions parameter is 6. But now we need to insert somehow our calculations into the value of the radius X. Copy the parameter of the radius of our circle, multiply by 1.5 and divide by sin(60), all in the value string. We get the following:
We got exactly what we wanted. Ok, let's move on. Now we should get the area. This is done with a single Measure node. It calculates the area by default. It is especially important not to forget to check the Total Attribute Name box. An area attribute is created then, which we will refer to later.
Let's go back to our model. I had to crop it by 2.5 mm on the open sides, as I wanted to keep 1 mm of the frame, and another 1.5 mm is our radius. Now you will understand why.
In the image and likeness, we take the Measure node, with the same checkmark, since it is the exact attribute that we will be comparing.
Add our main node called Scatter. The Generate parameter is By Density. Now we will set the number of points on the model in the Force Total Count parameter. We need to refer to the surface area attribute of the sculpture’s outer surface and divide it by the surface area of the hexagon. Referring looks this way: attrType("../nodeName","attrName",0).
Insert the surface area of the sculpture, place the division mark and insert the area of the hexagon. The Relax Iterations parameter for me usually ranges from 1000 to 10000. Just in case, I turn off the Randomize Point Order (what if you have to work with it), the Scale Radii By and Max Relax Radius parameters always change depending on the model. In 60% of cases, I leave them at default. You should try them yourselves.
What a wonderful pattern we get. One point is surrounded by 6 equidistant points, where possible, and 5 or 7 where necessary. Remember our truncated icosahedron.
I cropped the model so that the circles did not go beyond the boundaries of the sculpture, and even had an offset of 1 mm from the edges since Scatter generates points exactly along the edges of the surface (this is not the cropped model, but the original one):
Since I’ve come this far, all we need is to take the Copy to Points node, feed our Scatter to the Target Point to Copy to input, and the circle we created in the first steps to the Geometry to Copy input. Export all this together:
Often I create a cylinder near the desired radius and height, add a Boolean node, and immediately in Houdini, I have a preview of what I would get at the output. But I still prefer ZBrush.
Now I import everything into Modo, use the same Replicator on the resulting circles, and manually correct any problem areas if there are any. As described in Part II. Jump back and forth between ZBrush and Modo as before. And voila:
This method seems to be more natural from the point of view of the balance between the time spent and the result. No seams, no UVs, beautiful pattern edges, and preserved procedural approach. Perhaps it is not the most accurate of all, but here we’re solving problems of art with the help of mathematics, not solving mathematical problems at the expense of art.
Now I want to present to you the sculptures that have already been produced and exhibited. Thank you very much for taking the time to read, and I hope that someone will find some of the techniques from my practice helpful!