Have you ever used three.js? Have you ever wanted to see your work in 3D? Have you wondered how we got here, what the meaning of life is?
If your answer was yes to any of these questions, than you are in the right place! Here we are going to learn how to not only see things in 3D, but also make them move with just the flick of our wrist, the wave of our hands.
If you have never touched three.js before, your best bet is to check out one of the tutorials from someone who knows what they are doing ( which is most definitely not me ). Below are some good starting resources:
First we are going to quickly look at how to set up a three.js project with the camera controls,
but if you are comfortable with three.js, feel free to skip to slide 8, where we will begin looking
at LeapSpringControls
Please keep in mind that these controls are works in progress! If you have ideas on how they could be made better, have ideas of your own, or just want to tell me about typos / bugs, Check out the Repo or Hit me up on Twitter
Still with us? Good, than lets dive into some code right away!
The point of these Leap-Three-Camera-Controls is to make it as easy as possible to get something you've made to the point where it is using the Leap Motion Controller to make more magic. But before magic comes CODE!
The first thing we will do is to include all the files we need. For the purpose of this walkthrough, we will be defining the paths as we would in our examples, but keep in mind you will need to define your own paths:
<script src = "lib/three.min.js" ></script>
<script src = "lib/leap.js" ></script>
<script src = "controls/LeapTrackballControls.js" ></script>
Next slide we'll get the camera set up, and initialize our controller!
We will split the majority of our program into two parts: initialization, and animation.
Animation will take care of updating and rendering things, and will be called every frame.
Initialization will set up everything we need to use in the animation step. However, the
first thing that we need to do is create things that we will share between the two steps:
Global Variables!
// our leap controller
var controller;
// our leap camera controls
var controls;
// our three.js variables
var scene , camera , renderer;
Now that we've got the global variables defined, we can initialize them. We will be going over the THREE.JS initialization pretty quickly, so if it doesn't make sense to you, make sure you check out Aerotwist's three.js tutorial.
All of our code will be inside an init
function. This function can be called
wherever you want, but for this slide we are more concerned about what's INSIDE the function call
function init(){
// Setting up THREE.JS Scene / Camera / Renderer
var w = window.innerWidth;
var h = window.innerHeight;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50 , w / h , 1 , 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( w , h );
document.body.appendChild( renderer.domElement );
// Adding something to the scene just so we can see if it works
var geometry = new THREE.IcosahedronGeometry( 5 , 2 );
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh( geometry , material );
scene.add( mesh );
// HERE IS WHERE WE WILL INITIALIZE OUR CONTROLS
// IN THE NEXT SLIDE
}
We've got the THREE.JS part of the initialization out of the way, but we've done NOTHING to include that sweet nectar of motion control. So lets get to work on including all of things we need to create a Leap-Three-Camera-Control!
Keep in mind that this is the example for only ONE of the many camera controls. In later slides, we
will get to see how the different controls work. and play with their parameters, but for
this first example, we'll keep rolling with the LeapTrackballControls
// AFTER OUR THREE.JS INITIALIZATION
// first off, create our leap controller to get data from
controller = new Leap.Controller();
// To get frames rolling!
// Our Camera Controls, should do this on our own,
// but its good practice to say it outright!
controller.connect();
// THIS! is where the magic is.
// We pass in the camera ( what we are acting on )
// and the controller ( which gives us data )
controls = new THREE.LeapTrackballControls( camera , controller );
// Any defining of parameters, you can do here , like so:
controls.rotationSpeed = 20;
// but these parameters can also be updated anywhere else in the program!
// It is important to note that with other controls,
// we may pass through our scene,
// to add markers, placeholders and other visual feedback.
// We will explore this more in later slides
Now that we've got everything initialized, the only thing left to do is get frames rolling!
function animate(){
requestAnimationFrame( animate );
controls.update();
renderer.render( scene , camera );
}
Easy enough, right?
We done all the coding we need to do, so lets view it all together!
<html>
<body>
<script src = "lib/leap.min.js" ></script>
<script src = "lib/three.js" ></script>
<script src = "controls/LeapTrackballControls.js" ></script>
<script>
var camera , scene, renderer;
var controller , controls;
init();
animate();
function init(){
var w = window.innerWidth;
var h = window.innerHeight;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50 , w / h , 1 , 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( w , h );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.IcosahedronGeometry( 5 , 2 );
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh( geometry , material );
scene.add( mesh );
controller = new Leap.Controller();
controller.connect();
controls = new THREE.LeapTrackballControls( camera , controller );
controls.rotationSpeed = 20;
}
function animate(){
requestAnimationFrame( animate );
controls.update();
renderer.render( scene , camera );
}
</script>
</body>
</html>
Hopefully this all makes sense to you. If not, please check out A TUTORIAL . Or reach out to me at icohen@leapmotion.com || @cabbibo
Congrats! You are now a graphics programmer! And a Leap programmer! And super cool , and popular! And you understand how to use the controls, so we can move onto describing each one in detail.
Hopefully you don't look like this dude: but if you do, don't worry! now we get to actually start using the camera.
Whenever you are ready, head to the next slide to learn about LeapSpringControls
Spring controls attatch a spring from your camera to a target, which it is always looking at. When you pinch, it places a new anchor that the target will tween to, always giving you a smooth movement, while the spring pulls the camera toward the target. To see exactly what this means, try adding markers to the anchor , hand , and target as described in the below code snippet
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapEyeLookControls.js"></script>
// Inside Init Function
controls = new THREE.LeapSpringControls( camera , controller , scene );
controls.dampening = .75;
controls.size = 120;
controls.springConstant = 1;
controls.mass = 100;
controls.anchorSpeed = .1;
controls.staticLength = 100;
// Adding meshes to the Anchor , Target and Hand
var geo = new THREE.IcosahedronGeometry( 5, 2 );
var mat = new THREE.MeshNormalMaterial();
var targetMesh = new THREE.Mesh( geo , mat );
var anchorMesh = new THREE.Mesh( geo , mat );
var handMesh = new THREE.Mesh( geo , mat );
controls.addTargetMarker( targetMesh );
controls.addAnchorMarker( anchorMesh );
controls.addHandMarker( handMesh );
// Inside Animate Function
controls.update();
Using the following parameters:
The pointer controls always has the camera always pointing at a 'target', when you pinch, you begin moving the camera around the object, and when you release, the camera will stop moving.
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapPointerControls.js"></script>
// Inside Init Function
var controls = THREE.LeapPointerControls( camera , controller );
controls.size = 100;
controls.speed = .01;
controls.dampening = .99;
controls.target = new THREE.Vector3( 0 , 100 , 0 );
// Inside Animate Function
controls.update();
Using the following parameters:
Eye Look Controls are very similar to the Pointer controls. Infact when you use your right hand, they are exactly the same. The biggest difference is that when you use your left hand, you dynamically move the target. This leads to the ability to easily move around a scene, but always have a specific point you are focused on. Also, all movements are relative, rather than absolute.
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapEyeLookControls.js"></script>
// Inside Init Function
var controls = THREE.LeapEyeLookControls( camera , controller , scene );
controls.lookSize = 10;
controls.lookMass = 10;
controls.lookSpeed = 10;
controls.lookDampening = .9;
controls.eyeSize = 10;
controls.eyeMass = 10;
controls.eyeSpeed = 10;
controls.eyeDampening = .9;
// If you want to have a marker for your eye
// Which you probably do...
var geo = new THREE.CubeGeometry( 1 , 1 , 1 );
var mat = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh( geo , mat );
controls.addLookMarker( mesh );
// Inside Animate Function
controls.update();
Using the following parameters:
Two Hand controls let you translate around a scene by pinching with a single hand, and rotate scene when you pinch with two hands
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapEyeLookControls.js"></script>
// Inside Init Function
controls = new THREE.LeapTwoHandControls( camera , controller , scene );
controls.translationSpeed = 20;
controls.translationDecay = 0.3;
controls.scaleDecay = 0.5;
controls.rotationSlerp = 0.8;
controls.rotationSpeed = 4;
controls.pinchThreshold = 0.5;
controls.transSmoothing = 0.5;
controls.rotationSmoothing = 0.2;
// Inside Animate Function
controls.update();
Pinch Rotate Controls are nearly Identical to the Trackball controls, ( described next slide ) , except that they use pinch in order to move the camera. As well, they have the ability to zoom in and out, by simply pinching and moving inwards or outwards. In order to define when this happens, it looks at the movement in Z vs the movement in X and Y, and compares the two to see if there is more movement in Z than XY or vice versa
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapPinchRotateControls.js"></script>
// Inside Init Function
var controls = THREE.LeapPinchRotateControls( camera , controller );
controls.rotationSpeed = 10;
controls.rotationLowDampening = .98;
controls.rotationHighDampening = .7;
controls.zoom = 40;
controls.zoomDampening = .6;
controls.zoomSpeedRatio = 10;
controls.zoomCutoff = .9;
controls.zoomEnabled = true;
controls.zoomVsRotate = 1;
controls.minZoom = 20;
controls.maxZoom = 80;
// Inside Animate Function
controls.update();
Using the following parameters:
Trackball Controls let you swipe the camera around a target, as if you were pushing a giant bowling ball around ( your hand is always behind the ball ) Also , if you turn your hand straight up, and zoom is enabled, you will stop spinning and start zooming, based on moving your hand forward and backwards
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapTrackballControls.js"></script>
// Inside Init Function
var controls = THREE.LeapTrackballControls( camera , controller );
controls.rotationSpeed = 10;
controls.rotationDampening = .98;
controls.zoom = 40;
controls.zoomDampening = .6;
controls.zoomCutoff = .9;
controls.minZoom = 20;
controls.maxZoom = 80;
// Inside Animate Function
controls.update();
Using the following parameters:
Paddle Controls Let you 'paddle' Around a scene, the way that you would paddle through water. Pretty cool huh?
Pros:
Cons:
Pairings:
Called using:
<!-- Include Script -->
<script src="path/to/controls/LeapPaddleControls.js"></script>
// Inside Init Function
var controls = THREE.LeapPaddleControls( camera , controller );
controls.weakDampening = .99;
controls.strongDampening = .9;
controls.fingerMatchCutoff = .5;
controls.velocityMatchCutoff =.5;
controls.fingerMatchPower = 5;
controls.velocityMatchPower = 5;
controls.movementSpeed = 1;
controls.maxSpeed = 10;
// Inside Animate Function
controls.update();
Using the following parameters: