loading...
Cover image for Pointcloud effect in Three.js

Pointcloud effect in Three.js

maniflames profile image Maniflames ・4 min read

Not too long ago I built a site that served as a submission for a small competition. To spice it up, I decided to add some Three.js. An effect that has been on my mind for a pretty long time was the pointcloud. Austin Mayer has implemented a really cool one with effects on his website and I've been thinking about since I've seen it on his site.

Since the site had a little more to it, I decided to implement a super basic version of a pointcloud. Three.js provides a few functions that enable you to create a pointcloud pretty quickly.

Points instead of Mesh

A mesh (3d object) in Three.js consists of geometry and material. But instead of showing an entire mesh you just want to show the vertices. The Points class in Three.js can take a geometry and display points instead of the 'full' object. With PointsMaterial you are able to control the size of your points. The code for a 'pointcloud mesh' looks something like:

  let geometry = new THREE.TorusGeometry(10, 3, 16, 100)
  let material = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.25 })
  mesh = new THREE.Points(geometry, material)

  scene.add(mesh)

For the full code, click/press on the example and check out main.js in the code tab!

Using 3D models

It's possible to load 3D models in Three.js but you have to put in a little extra work. Depending on the format of the 3D model you have to load a loader in addition to the main library. I love to use .obj models myself so I personally need the OBJLoader.

If you load the library through an HTML tag you have to add an extra tag that loads a seperate script that comes with the Three.js download. This script can be found in examples/js/loaders/OBJLoader.js.

If you have included the entire folder loading it will be kind of like:

<script src="three/examples/js/loaders/OBJLoader.js"></script>

If you use npm, you can import the loader through the jsm folder. Keep using the js folder if you prefer the require syntax though! The import statements look something like this:

//import syntax
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'

//require syntax, require adds OBJLoader directly to THREE
require('three/examples/js/loaders/OBJLoader.js')

Loaders work a bit like an extend 'fetch' without promises. You insert a url of the file containing the model, the loader will execute a http request. You provide callbacks for a successful request, a request that is still in progress and an unsuccessful request.

You can get the geometry of the object you loaded by selecting the first child's geometry of the result.

const loader = new THREE.OBJLoader()
loader.load('https://cdn.glitch.com/fcf3c007-b4eb-4250-ba6b-653fdab94ce3%2Fjapanese_temple.obj?1558792651869',
(obj) => {
    // the request was successfull
    let material = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.25 })
    mesh = new THREE.Points(obj.children[0].geometry, material)
    mesh.position.y = -15 //this model is not exactly in the middle by default so I moved it myself
    scene.add(mesh)
},
(xhr) => {
    // the request is in progress
    console.log(xhr)
},
(err) => {
    // something went wrong
    console.error("loading .obj went wrong, ", err)
})

Small disclaimer: 3D models can be build in 3D modeling software like Autodesk Maya3D and Blender with geometry and 'modifiers'. If a very big part of the model is created with modifiers the points won't show up in a way you can 'see' the object when you apply the pointcloud. That's why it's very important that you always test 3D models you want to use specifically for this purpose.

A little control

Interactivity will always make something a lot more fun. Hover and morph effects like on Austin Mayer's site definitely take effort and time to create. But three has functionality you can quickly add to at least give users the ability to move the camera around with OrbitControls. Like 3D model loaders the controls are an extension you have to load. Orbit controls are located in examples/js/controls/OrbitControls.js (or examples/jsm/controls/OrbitControls.js using the import syntax). The code looks a little like this:

 camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  camera.position.z = 40

  const controls = new THREE.OrbitControls(camera)
  controls.enableZoom = false //zoom happens on scroll which can be quite annoying

I hope this helps as a 'getting started' on creating pointclouds in Three.js!

Credits

I got a lot of moral support from my best friend Sven, who also submitted a website to compete. I had a lot of doubt and wasn't sure wether I should submit anything at all. I'm glad he convinced me, because we are both be in Shanghai this winter πŸŽ‰. In case you want to know a little more, he wrote an article a while ago:

Posted on May 25 '19 by:

maniflames profile

Maniflames

@maniflames

Exploring graphics βœ¨πŸ’»

Discussion

markdown guide
 

As someone who's wanted to dive into three.js but has never used it so far, I think you did a great job of introducing it and getting me excited about trying it out. This is a seriously cool effect and you explained it well 😊

 

Mission accomplished in that case πŸ˜„

I hope you get the chance to try it out! I'm still exploring myself and can promise you it's worth your time. Thanks a lot for reading my post 😊

 

How did you embed the model as a cdn?

 

In this case the cdn is a feature of glitch. You upload assets into a project by clicking on 'assets' in the explorer on the left. You can drag any file type into there (you might need to compress your .ob file I used compress-or-die) and it will upload the file to glitch's cdn. If you click on the file, glitch will show you the url of the file. If you don't use glitch you should be able to use the path to your model.

Let me know whether you can find the stuff I'm talking about! Maybe I could help out by making a GIF, not gonna lie this feature isn't too intuitive πŸ˜…

 

a gif would be super helpful if you don't mind

So the thing is actually a little bit too big for a GIF so I made video instead.
I hope this helps, thanks for your patience!

Thanks alot... I managed to add more complex animations like Austin's site have a look:

wamaitha.netlify.com

I highly appreciate your input.

Super nice!! The morphs look really smooth, thanks for sharing your work 😁πŸ”₯πŸ’ͺ🏽

 

Great work man! If you ever want to play with a Leica #RTC360 hit me up. I'd love too see something from that scanner online...