I'm currently trying to remesh and simplify some protein structure models (very large) to reduce the file size of the STLs I need to print from.
The raw file before manipulation is ~4.9GB.
I'm currently attempting this on my home PC (16GB Ram, AMD FX9590, dual RX480s - so no slouch by any stretch) but I'm currently watching the progress (which isn't fast), and the RAM usage is worryingly close to 16GB now, with about 40% of the calculation still to go.
I'm using MeshLab's Quadratic Edge Collapse Decimation, to drop down by about 60% since there are a lot of redundance internal vertices etc and the print will already be quite difficult even with a small number of faces.
If my PC ends up not being able to handle this, does anyone know of any good commandline tools for Unix that I could use on one of my servers to handle remeshing and simplification, where I have considerably more ram and CPU power available.
First post on this SE, so apologies if this belongs somewhere different.
Netfabb came up in a number of suggestions that I found. Take a look at 3D Printing Under Arch Linux, which offers a number of solutions for Linux, including:
Taking the section on Netfabb:
netfabb Private will provide you with a fully-loaded tool-box to do all this and much more:
- fix complicated file errors
- make late design changes
- combine parts into one
- hollow out solid parts into a shell
- smooth the mesh to improve surfaces
- reduce file size
netfabb is not at official repository so you must install it from AUR using yaourt
$ yaourt netfabb-basic $ netfabb-basic
However, it is unclear as to whether there is a cmd line interface. It could be worth reading Problem in Netfabb Command Line execution and in particular the documentation on Automating Netfabb - although this seems to suggest that command line functionality is only available to users with Ultimate subscription and not Basic:
You can also decimate the model in Netfabb easily - Right click > Level of Detail > Choose something like 50%... or more or less depending on the level of detail needed.
Although, this isn't available in Basic subscription, or so says post #12.
I also came across this, non-command line option.
For example, you can give the free 3D modeling program Meshmixer a try. Choose the ‘Select’ tool from the menu on the right, then double-click on your model (this will select your entire mesh). Then click on the ‘Edit…’ option and select ‘Reduce’.
You can now reduce the polygon count using several options. The best working choice is to use the percentage tool. It will immediately tell you by how much percent your file size (and polygon count) has been reduced.
Available for Windows and OSX.
The meshlab tutorial is exactly what you want to do - the options described help preserve the overall geometry of the model while reducing the poly count. Start with a target of 150,000 polys and work up until the desired detail is retained, bearing in mind the printability I mentioned above.
Also, by way of Quora, How do I reduce the size of an STL file? Does it affect the CAD coordinates for 3D printing?, I also found this Meshmixer tutorial: Easy Guide on How to Repair Your .STL Files. Under the section Problem 4: File Size is too Large for 3D Printing are the following steps:
The last problem that you may stumble upon, particularly as your objects get larger and their complexity increases, is that the resulting
.stlfile size is too large for your 3D printer or 3D printing service of choice. Third party printing services like i.materialise or Shapeways have upload limits so you may have to change the size of your file (100 MB limit at imaterialise and 64 MB for Shapeways). It’s important to reduce the mesh without sacrificing the quality, which I should say at the outset is best done at the initial export from your CAD software to minimise any distortion. My number one quick tip is to make sure in the export settings that your saving in ‘Binary’ format, not ‘ASCII’ – it’s a significantly more compact file format for
.stl’s without losing quality). However if it’s not an option, Meshmixer can be really useful to quickly reduce file size and visualise how this will affect the quality of your surfaces.
For this example I’m going to return to the leaf from Problem 1, which as a
.stlfile is 30.757 MB – pretty large for such a small design and definitely over the limit for someone’s email if I wanted to send it. So let’s look at how we can get this under 10 MB.
- Select the entire model by pressing Ctrl + A on your keyboard to select all.
- Go to Edit>Reduce to bring up the options to reduce the mesh. Essentially the file size of a
.stlis directly related to the number of polygons (triangles) that make up all of the surfaces. We will use the Reduce tool to reduce the quantity of polygons, therefore reducing file size.
- The menu will give you a range of options to reduce the size of your file. The simplest is to use the default Percentage option, allowing you to determine the final file size you want rather than needing to know exactly how many triangles will be used to make up the file. In this case I have calculated that in order to get my original .stl file below 10 MB, I need a reduction of 70 % or more. As you adjust the values, you will get a preview of what your model will look like, allowing you to control how much reduction you employ before the model becomes too distorted and ‘pixelated.’
- Once you’re happy and have accepted the changes, you can click on the Export button or go to File>Export to save this new reduced
.stlfile. As you can see in the comparison below, there is almost no perceptible difference in the quality of the 30.757 MB file compared with the final reduced version at 9.362 MB. I have simply increased the size of the triangles, minimising the quantity needed to create the same volume. Your regular 3D printer, or even a highly accurate SLS printer will never even know the difference in a change like this. It’s only if you really go crazy with the file reduction that you might start to notice them in your final print (and in fact many of the low-poly models which are popular on Pinshape can be produced using this technique – start with a detailed .stl of the object you want, and then just keep reducing the number of triangles!).
Another option is to import the model into Blender, then use the Remesh or Decimate modifiers. Blender can be tough to get into initially but there are plenty of introduction tutorials on YouTube to help.
Blender does offer a Command Line Interface (CLI), see Command Line Arguments:
Usage: blender [args …] [file] [args …]
However, there doesn't appear to be an option for Remesh or Decimate. Although take a look at Is it possible to decimate or remesh via the CLI?:
Is there a way to execute this modifier from command line and export the result?
which then leads to Can modifiers be computed and applied from the command line?
You'd have to use
import bpy for obj in bpy.context.scene.objects: bpy.context.scene.objects.active = obj count = 1 length = len(obj.modifiers) while obj.modifiers: name = obj.modifiers.name print("%s: Applying %s (%d/%d)" % (obj, name, count, length)) bpy.ops.object.modifier_apply(modifier=name) count += 1 print("All done.")
For info on how to to run the above, see here.
Seeing as you are already using Meshlab, it might be worth reading Executing meshlab from commandline reduce faces of a mesh iteratively (awesomebytes/reduce_faces.py)
#!/usr/bin/env python import sys import os import subprocess # Script taken from doing the needed operation # (Filters > Remeshing, Simplification and Reconstruction > # Quadric Edge Collapse Decimation, with parameters: # 0.9 percentage reduction (10%), 0.3 Quality threshold (70%) # Target number of faces is ignored with those parameters # conserving face normals, planar simplification and # post-simplimfication cleaning) # And going to Filter > Show current filter script filter_script_mlx = """<!DOCTYPE FilterScript> <FilterScript> <filter name="Quadric Edge Collapse Decimation"> <Param type="RichInt" value="1448" name="TargetFaceNum"/> <Param type="RichFloat" value="0.9" name="TargetPerc"/> <Param type="RichFloat" value="0.3" name="QualityThr"/> <Param type="RichBool" value="false" name="PreserveBoundary"/> <Param type="RichFloat" value="1" name="BoundaryWeight"/> <Param type="RichBool" value="true" name="PreserveNormal"/> <Param type="RichBool" value="false" name="PreserveTopology"/> <Param type="RichBool" value="false" name="OptimalPlacement"/> <Param type="RichBool" value="true" name="PlanarQuadric"/> <Param type="RichBool" value="false" name="QualityWeight"/> <Param type="RichBool" value="true" name="AutoClean"/> <Param type="RichBool" value="false" name="Selected"/> </filter> </FilterScript> """ def create_tmp_filter_file(filename='filter_file_tmp.mlx'): with open('/tmp/' + filename, 'w') as f: f.write(filter_script_mlx) return '/tmp/' + filename def reduce_faces(in_file, out_file, filter_script_path=create_tmp_filter_file()): # Add input mesh command = "meshlabserver -i " + in_file # Add the filter script command += " -s " + filter_script_path # Add the output filename and output flags command += " -o " + out_file + " -om vn fn" # Execute command print "Going to execute: " + command output = subprocess.check_output(command, shell=True) last_line = output.splitlines()[-1] print print "Done:" print in_file + " > " + out_file + ": " + last_line if __name__ == '__main__': if len(sys.argv) < 3: print "Usage:" print sys.argv + " /path/to/input_mesh num_iterations" print "For example, reduce 10 times:" print sys.argv + " /home/myuser/mymesh.dae 10" exit(0) in_mesh = sys.argv filename = in_mesh.split('/')[-1] num_iterations = int(sys.argv) folder_name = filename.replace('.', '_') tmp_folder_name = '/tmp/' + folder_name + '_meshes/' print "Input mesh: " + in_mesh + " (filename: " + filename + ")" print "Num iterations: " + str(num_iterations) print "Output folder: " + tmp_folder_name try: os.mkdir(tmp_folder_name) except OSError as e: print >> sys.stderr, "Exception creating folder for meshes: " + str(e) exit(0) for it in range(1, num_iterations): if it == 1: out_mesh = tmp_folder_name + folder_name + "_it" + str(it) + ".dae" reduce_faces(in_mesh, out_mesh) else: out_mesh = tmp_folder_name + folder_name + "_it" + str(it) + ".dae" reduce_faces(last_out_mesh, out_mesh) last_out_mesh = out_mesh print print "Done reducing, find the files at: " + tmp_folder_name
here are some updates for python 3.6.2: https://gist.github.com/tylerlindell/7435ca2261e7c404ccc1241f18e483aa