DEV Community

Cover image for Pointcloud effect in Three.js
Maniflames
Maniflames

Posted on

Pointcloud effect in Three.js

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)


Enter fullscreen mode Exit fullscreen mode

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>


Enter fullscreen mode Exit fullscreen mode

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')



Enter fullscreen mode Exit fullscreen mode

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)
})


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

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:

Top comments (11)

Collapse
 
manutastic profile image
Manu

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 😊

Collapse
 
maniflames profile image
Maniflames

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 😊

Collapse
 
wamaitha profile image
wamaitha

How did you embed the model as a cdn?

Collapse
 
maniflames profile image
Maniflames • Edited

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 😅

Collapse
 
wamaitha profile image
wamaitha

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

Thread Thread
 
maniflames profile image
Maniflames

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!

Thread Thread
 
wamaitha profile image
wamaitha • Edited

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

wamaitha.netlify.com

I highly appreciate your input.

Thread Thread
 
maniflames profile image
Maniflames

Super nice!! The morphs look really smooth, thanks for sharing your work đŸ˜đŸ”„đŸ’ȘđŸœ

Collapse
 
ericguizzetti profile image
Eric Guizzetti

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...

Collapse
 
maniflames profile image
Maniflames

Thanks!

Collapse
 
leongeldsch profile image
Leon GeldschlÀger

Great introduction!
The one thing that I'm still wondering about, is how to create a morph effect between two point clouds. Let me know if you have any idea on how to get started with that!