Best way to create a word cloud in 3D space?

Hello everyone!

I plan to build a word cloud in a 3D space similar than the image below, where words (some would change over time) are spanned across the space and I can navigate through it. What would be the best and more clean approach without compromising much the performance?
Thanks in advance,

Joan

Hi, welcome to the forum,

Personally, I would use FontLoader to load a typeface font, in order to create one geometry per letter. Then I would use InstancedMesh to duplicate these letters without skyrocketing the number of draw calls.This way you would have one draw call per letter, so 26 for the English alphlabet, which is acceptable.

There is examples showing how to transform an individual InstancedMesh instance at runtime.

You would have to write an engine that position letters instances at the right place to form words in space. Information about letters dimension is contained in typeface font.

Beware that geometry text is sometimes dense in polygon, depending on the number of curves in a letter. An average T will be like 16 triangles, while an average S will be closer to 300. If you want to play with a complicated font like this, the triangle count may increase very quickly. An obvious workaround would be to model you own optimised glyphs in a 3D software.

The drawback is that you have to define a max number of instances when creating an InstanceMesh. So if you don’t control the words displayed, I imagine that you would have to resize the instance pool sometimes when the number of available letter ‘A’ for instance is exceeded, which is costly.

Another solution which is far simpler but less efficient for your use-case is to use this add-on I made for creating 3D user interface in three.js. It works completely differently : it does not work with instancing, and letters are not letters geometries, but simple planes with a letter texture on it. Then a shader post-process the texture so that it’s not pixelated, and transparent around the letter. It merge the letters geometries per block.

With your use-case, you would have a triangle count lower than with the InstancedMesh option, but one draw call per word, since in your case each word is in a separate block. If you have thousands like on your picture, it’s not acceptable, if you can go for 30 - 50 words, it’s fine.

3 Likes

Thanks @felixmariotto for your fast response! I am just starting with three.js so I’m not sure if I’m capable to achieve the first option you stated. However, I have some questions! If I understood well, do you suggest to duplicate each letter a number of times, let’s say 100 times for letter A, and having all these letters/geometries inside an InstanceMesh? Or have an InstanceMesh for each letter? Let’s assume I know the maximum number of instances and it will not vary.

Regarding to the second solution I would like to avoid using add-ons on my first three.js sketch attempt.

I’m not planning to display thousands of words, let’s say maximum would be 200 words. So, you think there is any other option which might be easier than your first solution and with no add-ons involved?

Thanks again,

Joan

Yes exactly this.

Granted this is a bit rough for a first three.js project…

An easier option involving no add-on (less efficient though) :

Take inspiration from this example. Look at the source code, it’s very short and clear, you can reproduce.

In this example a typeface font is loaded with FontLoader, then the font is used to create a geometry for the whole text, which is used to create a single mesh. If you do that for each word, you can easily move them around individually.

There is two problems with this process :

  • one draw call per word, so if you want 200 words, that’s a bit too much
  • too many triangles… for an average of 150 triangles per letter and an average of 4 letters per word, it’s 120 000 triangles. But with such a scene, I imagine that you want the letters to be visible from the back, so you would set Material.side to THREE.DoubleSide, and we end up with 240 000 triangles.

It will run, but not at 60FPS on low-end devices.

Another option, if you can accept that the words are static (can’t update, can’t move one from the other), is to merge the geometries. It’s similar to the process explained above, but instead of creating one mesh per word, you would merge all the word’s geometries together to create one single mesh. As you might expect, it’s difficult then to update a single word in this soup of geometries. Merging geometries is done with BufferGeometryUtils.mergeBufferGeometries.

With this second option, the number of triangles is still the same, but you have a single draw call.

You could also use a combination of these two solutions, and make batches of 10 words, maybe ? It depends on what you want to do exactly with you words.