Three.JS Multiple SkinnedMesh w/ Shared Skeleton

Demonstrates a multi-part character with a shared animated skeleton

HTML

<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/viewer3D.js?v=v6.1"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
<script src="https://raw.githubusercontent.com/mrdoob/three.js/master/src/math/Spherical.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://raw.githubusercontent.com/jeromeetienne/threex.sample/master/threex.sample.js"></script>
<script src="https://rawgit.com/mrdoob/stats.js/master/build/stats.js"></script>
<!doctype html>
<html>
<head>
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<div id="stats" class="stats"></div>
</body>
</html>

CSS

* {
  box-sizing: border-box;
}

body {
  background-color: black;
  font-family: sans-serif;
  font-size: 12px;
  padding: 0;
  margin: 0;
  overflow: hidden;
}

.infoBar {
  position: absolute;
  width: 100%;
  padding: 10px;
  color: lightGrey;
  text-shadow: 1px 1px 1px #000;
  z-index: 1;
}

.infoBar a {
  color: lightGrey;
}

.infoBar a.viewSourceLink {
  font-size: 10px;
  color: grey;
}

.stats {
  position: absolute;
  top: 30px;
}
.stats div {
  position: relative;
}

JavaScript

const SCREEN_WIDTH = window.innerWidth;
const SCREEN_HEIGHT = window.innerHeight;
const VIEW_ANGLE = 45;
const ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
const NEAR = 1;
const FAR = 10000;

let scene;
let camera;
let renderer;
let orbit;
let stats;
let lights;
let helper;

let mesh;

const origin = new THREE.Vector3(0, 0, 0);

function initStats() {
  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.left = '0px';
  stats.domElement.style.top = '20px';
  stats.setMode(0); // 0: fps, 1: ms
  document.getElementById('stats').appendChild(stats.domElement);
}

function init() {
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
  camera.position.set(20, 30, 40);
  camera.lookAt(origin);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

  // orbit = new THREE.OrbitControls(camera, renderer.domElement);

  // THREEx.WindowResize(renderer, camera);

  document.body.appendChild(renderer.domElement);

  initStats();

  // const gridHelper = new THREE.GridHelper(40, 10);
  // scene.add(gridHelper);

  // const axisHelper = new THREE.AxisHelper(2);
  // scene.add(axisHelper);

  lights = [];
  lights[0] = new THREE.PointLight(0xffffff, 1);
  lights[1] = new THREE.PointLight(0xffffff, 1);
  // lights[2] = new THREE.PointLight(0xffffff, 1);

  lights[0].position.set(200, 300, 400);
  lights[1].position.set(-200, -300, -400);
  // lights[2].position.set(-400, -500, 500);

  scene.add(lights[0]);
  scene.add(lights[1]);
  // scene.add(lights[2]);


    // Define bone/joint parameters

    const torsoLength = 6;
    const headLength = 3;
    const shoulderLength = 2;
    const shoulderSlope = 1;
    const upperArmLength = 3;
    const upperArmSlope = 1;
    const lowerArmLength = 3;
    const lowerArmSlope = 0;
    const hipLength = 2;
    const hipSlope = 1;
    const upperLegLength = 4;
    const upperLegSlope = 0;
    const...