Inverse Kinematics using CCD with Limit

by ikatyang

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r76/three.min.js"></script>
<script src="https://dl.dropboxusercontent.com/u/3587259/Code/Threejs/OrbitControls.js"></script>
<div class='top'>
  <a href='javascript:resetBallPosition()'>Reset Ball</a>
  ->
  <a href='javascript:arm.trace(ball.position, 20)'>Inverse Kinematics</a>
  ->
  <a href='javascript:shot()'>Shot</a>
</div>

CSS

.top {
  position: absolute;
  top: 1em;
  left: 0;
  right: 0;
  text-align: center;
}
body {
  margin: 0;
  overflow: hidden;
}

JavaScript

var scene, camera, renderer;
var controls;
var arm, ball, animated = false;
var clock = new THREE.Clock();

initArm();
init();
animate();

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

	camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
	camera.position.set(0, 200, 200);

	renderer = new THREE.WebGLRenderer();
	renderer.setSize(window.innerWidth, window.innerHeight);
	renderer.setClearColor(0x888888);
	document.body.appendChild(renderer.domElement);

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

	var gridXZ = new THREE.GridHelper(100, 10);
	gridXZ.setColors(new THREE.Color(0xff0000), new THREE.Color(0xffffff));
	scene.add(gridXZ);
	
	var armLink0 = new THREE.ArmLink(
		new THREE.Mesh(
			new THREE.CylinderGeometry(0.1, 0.1, 0.1),
			new THREE.MeshNormalMaterial()), {
		y: {
			min: -Math.PI * 2,
			max: Math.PI * 2
		}
	});
	var armLink1 = new THREE.ArmLink(
		new THREE.Mesh(
			new THREE.CylinderGeometry(5, 10, 60),
			new THREE.MeshNormalMaterial()), {
		x: {
			min: -Math.PI / 2,
			max: Math.PI / 4
		}
	});
	var armLink2 = new THREE.ArmLink(
		new THREE.Mesh(
			new THREE.CylinderGeometry(5, 10, 60),
			new THREE.MeshNormalMaterial()), {
		x: {
			min: 0,
			max: Math.PI * 2
		},
	});
	var armLink3 = new THREE.ArmLink(
		new THREE.Mesh(
			new THREE.CylinderGeometry(5, 10, 60),
			new THREE.MeshNormalMaterial()), {
		x: {
			min: -Math.PI / 4,
			max: Math.PI / 4
		},
	});
	arm = new THREE.Arm([armLink0, armLink1, armLink2, armLink3]);
	scene.add(arm);
	
	ball = new THREE.Mesh(
		new THREE.SphereGeometry(5, 32, 32),
		new THREE.MeshBasicMaterial({ color: 'black' }));
	resetBallPosition();
	scene.add(ball);
	
	var body = new THREE.Mesh(
		new THREE.BoxGeometry(50, 50, 50, 5, 5, 5),
		new THREE.MeshNormalMaterial({ wireframe: true }));
	body.position.set(-25, -10, 0);
	scene.add(body);
	
	var shot = new THREE.Mesh(
		new THREE.BoxGeometry(40, 60, 5),
		new...