3d Game Programming with Java and libGDX -3d Model Generation with OpenSCAD (‘drilling’ holes)

TL;DR¹

What You Will Need

  • Download OpenSCAD for your platform (it supports MacOS, Windows, and a variety of Linux distributions— at the time of writing it is version 2021.01.
  • The OpenSCAD cheatsheet open in a browser — which has a quick overview of all the commands (although there are tooltops to help you along)
  • Download blender for UV mapping exports and materials.

Why Use OpenSCAD

  • It is free, simple, actively maintained and it does exactly ‘what it says on the tin’.
  • The ability to do a ‘difference’ between 3d shapes is straight-forward in OpenSCAD (this use case is particularly nice when I was trying to ‘drill a hole’ through something in blender’).
  • It has good documntation on the functions.
  • It is text based, allowing me to source code control the code that I have written.
  • It is programmatic — I get to control every dimension for every part.
  • It has great debugging controls so I can see where I am going wrong (and right on the odd occasion).
  • You can use modules and imports to split up your files so that they don’t get too confusing — which, paradoxically can get confusing if you break up files too much.
  • OpenSCAD does not support materials, meaning that another tool would need to be used to apply these (Blender is used in this example).
  • The code part can get very complex very quickly, which can make it hard to determine at what point things are being done.
  • The Integrated Development Environment(IDE) is a little clunky and lacks support for some nice features (e.g. Renaming variables, easily commenting out sections, tooltips can sometimes disappear at the most inopportune moment).
  • Where you need to put semicolons ‘;’, or leave them out can be confusing until you figure out what the 3d rendering pipeline is attempting to do — and the commands that need to be done in order.

In This Guide

The final rendering of the mechanical pencil shaft with holes drilled through the model
$fn=50; // set the number of fragments
color("Gainsboro", 1.0) // metallic grey
difference() {
// outer shell with beveled edges
intersection() {
cylinder(h=10, r=4, $fn=6);
cylinder(h=10, r=3.9);
}
// inner cylinder to be removed
translate([0, 0, -0.5])
cylinder(h=11, r=3);
// all of the holes drilled through the outer shell
for(i = [0:60:360]) {
rotate([0, 0, i])
translate([3.4, 0, -0.5])
cylinder(h=11, r=0.25);
}
}

First Steps

Understanding the IDE

The splash screen for OpenSCAD version 2021.01
A screenshot of the OpenSCAD IDE showing the major parts of the screen
  1. File menu — saving, loading, and most importantly the rendering button (although every time that you save the code, it re-previews automatically).
  2. Code editing area (IDE) — where all of the code is typed.
  3. Rendering area — Where the 3d model is previewed/rendered.
  4. Rendering and view options —Preview/Render buttons, and ways to change the view on the rendering area.
  5. Console and error log — Useful when things go wrong to determine what has happened. Code parsing errors will also be highlighted in the ‘Code editing area (IDE)’

Set up your environment

The 3D View preference pane for OpenSCAD
cylinder(
OpenSCAD showing tooltips for a cylinder
  • h is the height of the cylinder
  • r, r1, r2 are the radii — you only need r if you are creating a cylinder, r1 and r2 for a cone
  • d, d1, d2 are the diameters — you only need d if you are creating a cylinder, d1 and d2 for a cone
  • center = true/false — whether you want to centre this about the origin (I personally recommend not doing this — i.e. leave the option out, or explicitly set it to center = false)
  • See the OpenSCAD documentation for full options for a cylinder
cylinder(h=10, r=5, center=false);
A simple cylinder is displayed with a one line OpenSCAD command
  • Use the mouse wheel to zoom in/out of a model
  • Right mouse button to pan
  • Left mouse button to rotate
  • Don’t forget to save your work
The rendered cylinder in close up
  1. let’s change the colour, by putting in a simple line before the cylinder
    color(“red”, 1.0) Note: that there is no semicolon ‘;’ after the command — this goes into the render pipeline and is reset after every render.
  2. Let’s increase the number of faces for the cylinder as well, using a special variable $fn — which is the number of fragments to render with. (OpenSCAD documentation on special variables). I am using the value of 50 which balances smoothness versus render time — remember that the more fragments that you have, the more UV unwrapping you will have to do, and the more processing that will need to be performed by the GPU to render it.
color("red", 1.0)
cylinder(h=10, r=5, $fn=50, center=false);

Let’s ‘drill’ a hole through the red cylinder

color("red", 1.0)
cylinder(h=10, r=5, $fn=50, center=false);
cylinder(h=10, r=4, center=false);
  1. The color has been reset to dark green — remember that I mentioned that the color command would reset after the execution of the pipeline.
  2. The cylinder is only partially visible — this is because there are some slight floating point arithmetic conflicts between the two cylinders, by which I mean that when the GPU calculates which of the cylinders should be shown, sometimes it comes up red, and sometimes it comes up green.

‘Drilling’ the hole

difference() {
color("red", 1.0)
cylinder(h=10, r=5, $fn=50, center=false);
cylinder(h=10, r=4, center=false);
}
The render rsult for both difference between cylinders
  1. The two ends of the green and red cylinders are overlapping.
  2. The green cylinder does not have as many faces as the red cylinder (a little bit hard to see.
  1. Set a default number of fragments for rendering of every every object that goes through the pipeline.
  2. Offset the green cylinder a little bit so that the difference can be shown.
$fn=50;  // set default number of fragments for all objectsdifference() {
color("red", 1.0)
cylinder(h=10, r=5, center=false); // removed $fn here
cylinder(h=11, r=4, center=false);
}
A rendering of the two cylinders with the bottom, still showing artefacts
$fn=50;difference() {
color("red", 1.0)
cylinder(h=10, r=5, center=false);
#cylinder(h=11, r=4, center=false); // debug command
}
Debugging mode for the green cylinder which is rendered with a transparent red cylinder
Artefacts for the bottom of the cylinder
Showing the bottom and top overlap with the debug cylinder
$fn=50;difference() {
color("red", 1.0)
cylinder(h=10, r=5, center=false);
translate([0,0,-0.5])
#cylinder(h=11, r=4, center=false);
}
Final render of a cylinder with a hole ‘drilled’ through it
$fn=50;color("red", 1.0)difference() {
cylinder(h=10, r=5, center=false);
translate([0,0,-0.5])
cylinder(h=11, r=4, center=false);
}

Now to Export…

  1. First Render the model (either pressing the F6 key, Using the menu Design -> Render, or clicking on the Render Icon)
  2. Export the Model as STL from the menu File -> Export -> Export as STL… (or just press the F7 key)

Import the Model into Blender

  1. Load up Blender
  2. Import the STL file File -> Import -> Stl (.stl)

Final Thoughts

$fn=50; // set the number of fragmentsheight_of_shell = 10;  // height of the outershell
offset = 1; // offset of the 'drill' cylinders
color("Gainsboro", 1.0) // metallic greyintersection() { difference() {
// outer shell with beveled edges
intersection() {
cylinder(h=height_of_shell, r=4, $fn=6);
cylinder(h=height_of_shell, r=3.9);
}
// inner cylinder to be removed
translate([0, 0, -0.5])
cylinder(h=height_of_shell + offset, r=3);
// all of the holes drilled through the outer shell
for(i = [0:60:360]) {
rotate([0, 0, i])
translate([3.4, 0, -(offset/2)])
cylinder(h=height_of_shell + offset, r=0.25);
}
}
union() {
translate([0,0, 0.5])
cylinder(h=height_of_shell, r=3.9);
translate([0,0, -4.5])
cylinder(h=5, r1=2, r2=4);
}
}
The mechanical pencel outer shaft showing slight bevel detail

Colophon

All sorts of interests

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Shopify Collection Filtering

Are your Python programs running slow? Here’s how you can make them 7x faster.

Tokenplay officially announced a partnership with Meeb Master to distribute NFTs Game

Importance Of Coding

A Trip to Objectville

【MACD】Optimize your MACD strategies with advanced indicators

Docker Essentials Part 1: Introduction and Definitions

A diagram of a virtual machine and a container. The VM structure has an infrastructure layer, then a hypervisor layer. Then, each virtual machine has its own operating system, and then its own further layers (a library and an app). The container structure has an infrastructure layer, then an operating system layer, then a container engine layer. Then, each container has its own further layers (a library and an app).

Using ACID transactions to combine queries and ensure integrity

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
synapticloop

synapticloop

All sorts of interests

More from Medium

Improve Tesseract OCR accuracy with spellchecking

Millicast 2.0 — Interactive Video & Audio API

Technical features of the InvArch project

Expo Part 2: History