How we built our polygon heads

Thomas Digby

With the launch of our shiny new studio site, we’re taking the chance to experiment with ways to introduce the Shortlist digital team.

Early on in the prototyping phase for our new site we were lucky to have the chance to play with a Structure Sensor, a 3D scanning peripheral for iPhone and iPad.

After hours of mindless scanning we all agreed there couldn’t possibly be any other way of presenting our team than over-stylised, low-poly, interactive 3d models. Right?

One of the initial scans we produced of our handsome Product Manager Will is embedded below through Sketchfab.

We quickly moved onto low-poly prototypes of our heads, attempting some destructive transformations in Meshlab.

The sharply named Quadratic Edge Collapse Decimation method reduced the polygon count by removing a polygons closest neighbour without affecting the overall shape of the model. By reducing the total number of polygons the model would slowly reduce in complexity and render our desired low-poly look.

How we built our polygon heads

Unfortunately these models tended to err on the generic side and what started as an attempt to show the different personalities in the team ended up as a collection of personality-less 90’s video game models.

This is where the professional comes in! Handing over our original scans and some basic 360 degree photos of each subject, we asked a chap named Petr to transform them into carefully considered low-poly models with hand-crafted textures achieving the look we were after.

Polygon pun. 1

Just look at those glasses.

When it came to implementing the models there were a few things to keep in mind. As the colours were embedded into the model, we had to use the `MeshPhongMaterial`. This allowed us to transfer each polygons face colour from our model onto the vertex colours of the material. Implementing this took a little bit of trial and error, there are enough unique materials, geometries and combinations of both to be quite confusing at times. Shading is an important property, without declaring `THREE.FlatShading` each vertex colour would blend with its closest sibling.

With those issues tied up, a basic example of the loader and material can be seen below.

// define loader
const loaderPly = new THREE.PLYLoader(new THREE.LoadingManager())
// request model
loaderPly.load(this.modelUrl, geometry => {
  // create new material and set texture
  const material = new THREE.MeshPhongMaterial({
    shading: THREE.FlatShading,
    shininess: 20,
    vertexColors: THREE.FaceColors
  // create new mesh from .ply geometry and mesh material
  this.object = new THREE.Mesh(geometry, material)
  // add to scene

We’re really happy with this first implementation of our 3d team, and without really knowing what we’d end up with, that each team member has their own presence and personality is just what we were after. Of course now we have our 3d-heads, we have many, many ideas to build upon.

As an added bonus, any future members of our digital team here at Shortlist will be presented with their very own low-poly, hand-crafted 3d head. And at the end of the day, I think truly that’s all any of us want out of a job.