JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="http://threejs.org/examples/js/controls/TransformControls.js"></script>
<script src="http://eddy.cx/dev/3d/models.js"></script>

CSS

body { overflow: hidden; }

JavaScript

var inner = new THREE.Object3D(),
    arm   = new THREE.Object3D(),
    model = new THREE.Object3D();

function angle3D(a, b) {
	var dot = a.dot(b);
	return Math.acos(dot / (a.length() * b.length()));
}

function angleFromDirection(a, b, ref) {
	var absAngle = angle3D(a, b);

	a.cross(b);
	var dot = a.dot(ref);

	return (dot < 0 ? -absAngle : absAngle);
}

function angleFromDirection_proj(upDirection, lookDirection) {
	var Yproj = new THREE.Vector3(  -(lookDirection.y * lookDirection.x),
								  1 -(lookDirection.y * lookDirection.y),
								    -(lookDirection.y * lookDirection.z));
	Yproj.normalize();

	return angleFromDirection(upDirection, Yproj, lookDirection);
}

function mappedVector(mat, x, y, z) {
    return (new THREE.Vector3(x, y, z)).applyMatrix3(mat).normalize();
}

function calculateAngles() {
	var mat = new THREE.Matrix3();
	mat.getNormalMatrix(model.matrix);
	
	debugVector(mappedVector(mat, 1, 0, 0), "blue");
	debugVector(mappedVector(mat, 0, 1, 0), "red");
	debugVector(mappedVector(mat, 0, 0, 1), "yellow");
	
	mat.transpose();
    
	var pitch = angleFromDirection(mappedVector(mat, 0, 1,  0),
                                   new THREE.Vector3(1, 0,  0),
                                   mappedVector(mat, 0, 0, -1));
    
    var roll  = angleFromDirection(mappedVector(mat, 0, 1,  0),
                                   new THREE.Vector3(0, 0,  1),
                                   mappedVector(mat,-1, 0, -1));
    
	var yaw   = angleFromDirection(mappedVector(mat, 0,  0, 1),
                                   new THREE.Vector3(1,  0, 0),
                                   mappedVector(mat, 0, -1, 0));    
    pitch -= Math.PI/2;
	roll  += Math.PI/2;
    yaw   -= Math.PI/2;
    
	updateSimAngles(-pitch, -roll);
}


////////////////////////////////////////////////
// No need to change anything below this line
////////////////////////////////////////////////
function updateSimAngles(pitch, roll) {
    if (!inner || !arm)
        return;
    
  ...