How to convert and render STL files to images

Cubehero isn’t just the web page itself. It depends largely on background workers to do the work of rendering models to images, resizing images, and visual diffing models. The past three weeks have been an overhaul of the system to better support background workers.

Update: We’ve now wrapped this up into a library called stljs, which lets you read, write, and render STL files without having to do it by hand

For you, the user, this means being able to see clear representations of the files you’ve uploaded. If it’s a photo, you get different sizes of the photo. If it’s an STL file, you see an image of the rendered model. Even if you don’t upload a photo for your physible, you will see image of the model.

image of physible overview page showing resized images

We can render a model to provide image previews

So how do you render or convert STL files to images? Here, we’ll detail a manual way to do it. Soon, we’ll release a library that does this for you.

To convert STL files to images, you use programs called raytracers, which take a 3D model or scene, and render it as a picture. They do this by modeling how light bounces travels from a light source, bounces off an object, and gets captured by the camera. Raytracers are pretty sophisticated programs that can generate very realistic scenes, but for us, our models and scenes are relatively simple, so they don’t take very long.

There are different ways to do this, but here I’ll detail the manual way to render images from STL files. We’ll be using a raytracer called Pov-ray. If you’re on a mac, you can install it using homebrew.

brew install povray

If you’re using ubuntu, you can install it using aptitude

aptitude install povray

However, povray doesn’t directly read STL files. We’ll need to convert them into a format they can read, which are POV files. POV files can contain both the data of the model, and the instructions of how to render the scene, such as how much lightning, and what position and angle to put the camera.

A tutorial on the ins and outs of a POV file would be beyond the scope of this post, but we can start with a simple one. First, we’re going to put the data and the rendering instructions different files for clarity. We’ll put the data in a file called ‘my_model.inc’, and then include it in ‘my_model.pov’, which contains the rendering instructions of the POV file.

We can data dump the STL file into my_model.inc by using an old C program called stl2pov. Download the project and compile using ‘make’. Then use the compiled executable stl2pov to convert your STL to a POV include file with:

stl2pov my_model.stl > my_model.inc

Next, we declare the rendering instructions for the POV file, called ‘my_model.pov’. Open up ‘my_model.inc’ with a text editor, and note what name it declares the model. In my case, it’s ‘m_OpenSCAD_Model’. You’ll need to replace ‘m_OpenSCAD_Model’ with the name of your own model in the ‘my_model.pov’ below.

#include "./my_model.inc"
#include "math.inc"
#include "finish.inc"
#include "transforms.inc"
background {color rgb 1}
light_source {
  <-500,500,400>
  rgb 1
  shadowless
}
global_settings {
  assumed_gamma 2
}
#declare Min = min_extent(m_OpenSCAD_Model);
#declare Max = max_extent(m_OpenSCAD_Model);
#declare bottom_diag = sqrt(pow(Max.y - Min.y, 2) + pow(Max.x - Min.x, 2));
#debug concat("bottom_diag:", str(bottom_diag, 5, 0))
#declare box_diag = sqrt(pow(bottom_diag, 2) + pow(Max.z - Min.z, 2));
#debug concat("box_diag:", str(box_diag, 5, 0))
#declare look_angle = degrees(tanh((Max.z - Min.z) / (bottom_diag / 2)));
#declare look_at_z = (Max.z - Min.z) / 2;
#debug concat("look_at:", str(look_at_z, 5, 0))
camera {
  orthographic
  location <0,box_diag + 1,0>
  rotate <look_angle,0,40>
  look_at <0,0,look_at_z>
}
sky_sphere {
  pigment {
  gradient y
  color_map {
    [0.0 rgb <1.0,1.0,1.0>] //153, 178.5, 255 //150, 240, 192
    [0.7 rgb <0.9,0.9,0.9>] // 0, 25.5, 204 //155, 240, 96
  }
  scale 2
  translate 1
  }
}
object {
  m_OpenSCAD_Model
  texture {
    pigment {color <1,1,1>}
    finish {phong 0.0}
  }
}

Once we have these two files, we can use povray to render the model.

povray -s -i"my_model.pov" +FN +W320 +H240 -o"my_model.png" +Q9 +AM1 +A +UA

And that’s it! Enjoy your new image. If you’d like to change the angles and the lightning, change the parameters in ‘camera’ section in ‘my_model.pov’. For more, try the documentation on pov-ray. If this all seems like a hassle to do manually, we’ll have a library that does this for you soon.

Want to learn more? follow me on twitter.

Advertisement
Tagged with: ,
Posted in tutorial
11 comments on “How to convert and render STL files to images
  1. Carlos says:

    Hi! Great tutorial but it doesn’t seem to work for me 😦
    The name that appears in the “.inc” file is OpenSCAD_Model, I changed it in the “.pov” file and run the command. This error appears:

    File ‘dock.pov’ line 14: Parse Error: Expected ‘)’, undeclared identifier
    ‘OpenSCAD_Model’ found instead

    What could be the problem?
    Thank you!

    • iamwil says:

      Hrm, I double checked it just now, and it does work for me. In your dock.pov file, look on line 14, and see that you have a missing ‘)’ at the end. I suspect that when you changed the name, you also erased the closing parenthesis. Don’t forget the semicolon at the end!

      • Carlos says:

        My 14 and 15 lines look like this:
        #declare Min = min_extent(OpenSCAD_Model);
        #declare Max = max_extent(OpenSCAD_Model);

        By the way, the link you posted for stl2pov is down. I downloaded it from a different source and I don’t know if that could be the problem

      • iamwil says:

        Hrm, if that’s the case, your guess is as good as mine. I’ve looked in the POV-mesh file, *.inc, and there aren’t parenthesis. As far as I can tell, you have a stray unmatched parens somewhere. Double check both the pov and inc file.

    • iamwil says:

      I just thought of another thing. Make sure you include the *.inc file at the very top.

      • Carlos says:

        Yep, I included it.
        #include “./dock.inc”

        The top line of my dock.inc file is:
        // Name of the solid: OpenSCAD_Model

        That is the name that I should put on the .pov file right?

      • iamwil says:

        Yes, what you have is correct. If that’s the only error, I’m mystified. You probably are using the name OpenSCAD_Model before you’ve declared it with the *.inc file. I’m packaging it up in a library that I’ll release soon, so you don’t have to mess around with it manually.

    • phbernard says:

      I had the same issue. I fixed it by adding the “-s” option to stl2pov. Actually, the command line of povray contains a “-s” option but I don’t get its role. Maybe stl2pov and povray commands line options were somehow mixed.

      To understand the difference the “-s” option makes, open the generated .inc file. With the “-s” option, m_OpenSCAD_Model is properly declared. Without “-s”, the string “m_OpenSCAD_Model” appears only in comments.

  2. […] a fast library for reading, writing, and rendering STL files. In the last post, we wrote about how to convert and render STL to images manually, but now, you can have stljs to do it for […]

  3. Rainer says:

    The cubehero link in the text at the beginning is broken.

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 )

Facebook photo

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

Connecting to %s

%d bloggers like this: