Posted By

João Martins
Joined the Developer Advocates team in 2020, João works mostly with .NET application. He is a Civil Engineer graduate with experience in software development. You can count on him to help you with your AEC related topics.
8 Jul 2021
This will be the first of a series of three blog posts covering methods for adding labels to your models.
In this part, we'll be focusing more on how to add text geometry as labels into Forge Viewer.
Maybe you are trying to...
In this Three part blog series, we are going to cover all things “labels”, including past blogs and techniques.
Let's start by summarizing three popular options:
The first approach, HTML elements, has been posted before.
The HTML elements technique changes the Top/Left values of a DIV/SVG element. The HTML canvas is rendered above the Forge-Viewer webGL layer. We move the labels (DIV) x,y position every frame, based on a calculation (re-projecting a 3D point from three.js to the 2D viewport).
That is a slow technique, but very convenient – It’s slow because the DIV Labels layer (HTML rendered by Skia) is drawn over the top of the 3D WebGL layer (rendered by three.js). This causes over-draw.
We can improve the DIV Label speed, a little, by using ‘fixed’ CSS positioning, to get GPU acceleration, but unfortunately, the over-draw inefficiencies, cannot be avoided.
There’s more. Let's summarize the pros and cons:
Pros:
Cons:
Now, let us look at an alternative approach...
What if we create text as three.js geometry? We do this by creating a three.js shape for each font’s character.
What are the Pros?
Cons:
Below we can see the tesselation of the geometry, forming the letters through triangle meshes.
Now let's cover the steps to use this approach.
First up, Forge-Viewer is still using V71. So we can't add our text using the default method (refer here). Thankfully, not a whole lot has changed, to make things work - just a couple of name changes, like THREE.FontLoader()
Next, let’s create a TextGeometry mesh, and add it into a scene (Forge Viewer overlay)...
//First we create the TextGeometry
let geom = new THREE.TextGeometry(text, {
font: "monaco",
size: size * 25,
height: 0,
curveSegments: 3,
});
//Here we compute it's boundingbox
geom.computeBoundingBox();
//Here we define the material for the geometry
var mat = new THREE.MeshBasicMaterial({ color: this.color });
//Here we create the mesh from using the geometry and material
this.mesh = new THREE.Mesh(geom, mat);
//Then, we set its position
this.mesh.position.x = -65;
this.mesh.position.y = -10;
this.mesh.position.z = 5;
//Now we just need to add on a custom scene on viewer
this.viewer.overlays.addScene('custom-scene');
this.viewer.overlays.addMesh(this.mesh, 'custom-scene');
I like the monaco.TTF true-type font, used by Sublime Text Editor, and I want to use this font style inside my three.js scene. You can find a copy from the author here
First, I upload monaco.TTF to this website FaceType.js
This will generate a special ‘js’ file that helps the TextGeometry three.js class. Download this js, and load and reference it in your app.
Something like this...
<script src=" <your-font>.js"></script>
We're almost done, but if you try to load it this way, you might get an error like:
Unhandled Promise Rejection: The font <your-font-name> with normal weight and normal style is missing.
If we take a look at our recently generated js font, we can see it verifies both _typeface_js and _typeface_js.loadFace.
That's our third step, we need to ensure _typeface_js object is defined and have faces and loadFace methods referencing to THREE.FontUtils.faces and THREE.FontUtils.loadFace respectively.
That can be done by adding the script below before loading <your-font>.js:
<script>
self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };
</script>
And that's it.
To summarize, here are the steps:
We'll go further on 3D CSS in the next blog post.
Here’s a live demo:
You can follow me on twitter: twitter.com/JooPaulodeOrne2