A slightly convoluted example, showing how to enable d3.js’s zoom behavior on a 3D scene with ortographic camera in three.js (see the previous example). Since moving the camera seems difficult (and not supported by three.js’s built-in controls), the code acts on the camera extents (top, bottom, left and right) and updates its projection matrix explicitly.
A different method for specfifying camera orientation is also used, which needs the definition of the camera’s up vector.
// Generated by CoffeeScript 1.4.0
(function() {
var DZOOM, OX, OY, aspect, camera, height, light, loader, render, renderer, scene, view, width, zoom;
width = 960;
height = 500;
aspect = width / height;
DZOOM = 10;
scene = new THREE.Scene();
camera = new THREE.OrthographicCamera(0, 2 * DZOOM * aspect, 0, -2 * DZOOM, -1000, 1000);
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, -20, 15);
scene.add(light);
OX = -35;
OY = -5;
camera.position.set(OX + 20, OY - 20, 20);
camera.up = new THREE.Vector3(0, 0, 1);
camera.lookAt(new THREE.Vector3(OX, OY, 0));
render = function() {
return renderer.render(scene, camera);
};
loader = new THREE.ColladaLoader();
loader.load('CNR_master.dae', function(collada) {
collada.scene.scale.set(0.005, 0.005, 0.005);
scene.add(collada.scene);
return render();
});
view = d3.select(renderer.domElement);
zoom = d3.behavior.zoom().scaleExtent([0.2, 4]).on('zoom', function() {
var x, y, z, _ref;
z = zoom.scale();
_ref = zoom.translate(), x = _ref[0], y = _ref[1];
return window.requestAnimationFrame(function() {
x = x - width / 2;
y = y - height / 2;
camera.left = -DZOOM / z * aspect - x / width * DZOOM / z * 2 * aspect;
camera.right = DZOOM / z * aspect - x / width * DZOOM / z * 2 * aspect;
camera.top = DZOOM / z + y / height * DZOOM / z * 2;
camera.bottom = -DZOOM / z + y / height * DZOOM / z * 2;
camera.updateProjectionMatrix();
return render();
});
});
view.call(zoom);
}).call(this);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>3D Building with zoom and pan (three.js)</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/r69/examples/js/loaders/ColladaLoader.js"></script>
</head>
<body>
<script src="index.js"></script>
</body>
</html>
width = 960
height = 500
aspect = width/height
DZOOM = 10
scene = new THREE.Scene()
# this is configured to have the upper-left corner as origin
camera = new THREE.OrthographicCamera(0, 2*DZOOM*aspect, 0, -2*DZOOM, -1000, 1000)
renderer = new THREE.WebGLRenderer
alpha: true
antialias: true
renderer.setSize(width, height)
document.body.appendChild(renderer.domElement)
# create the light
light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(10, -20, 15)
scene.add(light)
# set the camera (upper-left corner!)
OX = -35
OY = -5
camera.position.set(OX+20, OY-20, 20)
camera.up = new THREE.Vector3(0,0,1)
camera.lookAt(new THREE.Vector3( OX, OY, 0 ))
render = () ->
renderer.render(scene, camera)
# load DAE
loader = new THREE.ColladaLoader()
# loader.options.convertUpAxis = true
loader.load 'CNR_master.dae', (collada) ->
collada.scene.scale.set(0.005,0.005,0.005)
scene.add collada.scene
render()
# pan and zoom
view = d3.select(renderer.domElement)
# define a zoom behavior
zoom = d3.behavior.zoom()
.scaleExtent([0.2,4])
.on 'zoom', () ->
z = zoom.scale()
[x, y] = zoom.translate()
window.requestAnimationFrame () ->
x = x-width/2
y = y-height/2
camera.left = -DZOOM/z*aspect - x/width*DZOOM/z*2*aspect
camera.right = DZOOM/z*aspect - x/width*DZOOM/z*2*aspect
camera.top = DZOOM/z + y/height*DZOOM/z*2
camera.bottom = -DZOOM/z + y/height*DZOOM/z*2
camera.updateProjectionMatrix()
render()
view.call(zoom)