This post you’ll learn about how to load triangle meshes into ShapeJS and a method to protect functional areas in your design. Our goal this week is to design a lightswich cover that is customized with a user image. I started this process by finding common measurements of light switches and thinking about how to 3D model it. I quickly got into wanting a script that could handle n toggles, different hole types, phone and audio connectors, it got complicated fast! Then I found some already 3D modeled versions in different model repositories and became lazy. The final form of this script takes a 3D triangle model as its base object and then overlays the user image. Let’s start with a photo of the final object to get us inspired:

To understand how we load 3D models into ShapeJS it helps to understand the internal representation we use. All datasources in ShapeJS calculate a signed distance function. This is zero on the surface of the object, negative inside and positive outside. The function for loading a 3D model from your code is called loadModelDistance. It takes the file name, a voxelSize and the maximum distance to calculate. The voxel size controls the resolution we load the model and how fast it loads. For small models I use 0.1mm, but for something larger like this model I use 0.2mm. For the distance, you want to use a distance out to the maximum place your edit the model. For our light switch cover we’ll be embossing our image up about 1mm so I calculate the distance function to 1.2mm. Think of a cloud surrounding your model, you need this cloud to intersect anything you’ll doing to the model such as adding or subtracting material. You don’t need to be super accurate about this, but the farther out you calculate it, the longer the calculation takes.

Let’s start by just loading the model itself.

var params = [
{
name: "model",
label: "Model",
desc: "3D Model of light switch",
type: "uri",
defaultVal:"https://www.shapeways.com/rrstatic/javascript/shapejs/examples/models/Light_Switch_Plate1.stl"
}
];

function main(args) {
var base = loadModelDistance(args.model, 0.1 * MM, 1.2 * MM);
var bounds = base.getBounds();

return new Scene(base, bounds);
}

For the basic light switch cover it looks like this:

Currently we support loading STL and X3D files. The X3D files currently ignore the color information and just load the geometry. When you load the model it will return an object with a bounds property. You can use that bounds property to set your scene bounds.

From there we can start adding in the user images. The way I thought about this was to reuse the Image3D datasource. This loads an image and makes 3D geometry out of it. In this case we are going to extrude it up by 1mm. One problem with this concept is it will block the functional areas of our model. In this case we need to protect the two screw holes and the square light switch rocker area. To do this we are going to model the protected areas and then subtract those from the pattern. The makeImage method takes our user image and the makePattern method subtracts out a box and two holes to protect the design.


function makeImage(path, w, h, d) {

var img = new Image3D(path, w, h, d);

img.setBlurWidth(0.2 * MM);
img.setImagePlace(Image3D.IMAGE_PLACE_TOP);
img.setCenter(0, 0, 3.5 * MM);
img.setUseGrayscale(false);

return img;
}

function makePattern(path) {
var box = new Box(12.5 * MM, 25.5 * MM, 15 * MM);
var hole1 = new Cylinder(new Vector3d(0, -30.674 * MM, 0), new Vector3d(0, -30.674 * MM, 25 * MM), 5.5 * MM);
var hole2 = new Cylinder(new Vector3d(0, 29.805 * MM, 0), new Vector3d(0, 29.805 * MM, 25 * MM), 5.5 * MM);

var img = makeImage(path, 64.16 * MM, 106.185 * MM, 1 * MM);

var holes = new Union();
holes.add(box);
holes.add(hole1);
holes.add(hole2);

return new Subtraction(img, holes);
}

You can run the full example here: Light Switch Cover Example

I think this design came nice. I also tried it in our Blue material:

One variant I tried was to cut the pattern completely through the original model instead of embossing it. Looking at the 3D model itself I really like this better, plus is was much cheaper. That said I found out quickly that looking inside an electrical box is not the prettiest of things. Seems the original designers had the right idea of covering that stuff up!

Couple of notes about this project. This current script embossed 1mm of material on top of an existing model. The model itself is pretty darn strong printed in plastic, so I feel like adding more material is not necessary. Perhaps engraving the design would work well and cost less. The second note is about costs. I looked around on Etsy and Amazon to get an idea of whether this concept would work. Typically 3D printed items are more expensive then their mass produced cousins. On Amazon I found single light switch covers ranging from 0.25 for a very basic model to $20 for a fancy model. On Etsy they range from $5 to $32. This design costs around $18 currently. I’d say that puts this in the ball park of a good concept that could compete on price and allow the user to create whatever design they want. This method is also applicable to other objects you’d like to put designs on such as a phone case. Take a base 3D model of the case, model the functional areas in the case you want to protect such as the camera and controls and there you go. Instant phone case creator!