Skip to content

Commit 3174dc2

Browse files
committed
added zoom and pan to TrackballCamera
1 parent 902e316 commit 3174dc2

File tree

1 file changed

+107
-23
lines changed

1 file changed

+107
-23
lines changed

src/extras/cameras/TrackballCamera.js

Lines changed: 107 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* }
2121
*/
2222

23+
// TODO: onWindowResize();
24+
2325
THREE.TrackballCamera = function ( parameters ) {
2426

2527
THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target );
@@ -50,10 +52,11 @@ THREE.TrackballCamera = function ( parameters ) {
5052

5153
this.useTarget = true;
5254

53-
this.mouseDragOn = false;
54-
55+
this.state = this.STATE.NONE;
5556
this.screen = this.getScreenDimensions();
5657

58+
this.mouse = new THREE.Vector2();
59+
5760
this.start = new THREE.Vector3();
5861
this.end = new THREE.Vector3();
5962

@@ -67,6 +70,8 @@ THREE.TrackballCamera = function ( parameters ) {
6770

6871
};
6972

73+
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
74+
7075
this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
7176
this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
7277
this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false );
@@ -80,6 +85,13 @@ THREE.TrackballCamera.prototype = new THREE.Camera();
8085
THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera;
8186
THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype;
8287

88+
THREE.TrackballCamera.prototype.STATE = {
89+
NONE : -1,
90+
ROTATE : 0,
91+
ZOOM : 1,
92+
PAN : 2
93+
};
94+
8395
THREE.TrackballCamera.prototype.handleEvent = function ( event ) {
8496

8597
if ( typeof this[ event.type ] == 'function' ) {
@@ -106,32 +118,42 @@ THREE.TrackballCamera.prototype.mousedown = function(event) {
106118

107119
event.preventDefault();
108120
event.stopPropagation();
109-
110-
this.mouseDragOn = true;
111121

112-
this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
122+
if ( this.state === this.STATE.NONE ) {
123+
124+
this.state = event.button;
125+
126+
if ( this.state === this.STATE.ROTATE ) {
127+
128+
this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
129+
130+
} else {
131+
132+
this.mouse = this.getMouseOnScreen( event.clientX, event.clientY );
133+
134+
}
135+
136+
}
113137

114138
};
115139

116140
THREE.TrackballCamera.prototype.mousemove = function( event ) {
117141

118-
if ( this.mouseDragOn ) {
142+
if ( this.state === this.STATE.NONE ) {
119143

120-
this.end = this.getMouseProjectionOnBall( event.clientX, event.clientY );
144+
return;
121145

122-
var angle = Math.acos( this.start.dot( this.end ) / this.start.length() / this.end.length() );
146+
} else if ( this.state === this.STATE.ROTATE ) {
123147

124-
if ( angle ) {
148+
this.rotateCamera( event.clientX, event.clientY );
125149

126-
var axis = (new THREE.Vector3()).cross( this.end, this.start ).normalize(),
127-
quaternion = new THREE.Quaternion();
150+
} else if ( this.state === this.STATE.ZOOM && !this.noZoom ) {
128151

129-
quaternion.setFromAxisAngle( axis, angle );
152+
this.zoomCamera( event.clientX, event.clientY );
130153

131-
quaternion.multiplyVector3( this.position );
132-
quaternion.multiplyVector3( this.up );
154+
} else if ( this.state === this.STATE.PAN && !this.noPan ) {
133155

134-
}
156+
this.panCamera( event.clientX, event.clientY );
135157

136158
}
137159

@@ -142,7 +164,7 @@ THREE.TrackballCamera.prototype.mouseup = function( event ) {
142164
event.preventDefault();
143165
event.stopPropagation();
144166

145-
this.mouseDragOn = false;
167+
this.state = this.STATE.NONE;
146168

147169
};
148170

@@ -170,30 +192,92 @@ THREE.TrackballCamera.prototype.getScreenDimensions = function() {
170192

171193
};
172194

195+
THREE.TrackballCamera.prototype.getMouseOnScreen = function( clientX, clientY ) {
196+
197+
return new THREE.Vector2(
198+
( clientX - this.screen.offsetLeft ) / this.radius * 0.5,
199+
( clientY - this.screen.offsetTop ) / this.radius * 0.5
200+
);
201+
202+
};
203+
173204
THREE.TrackballCamera.prototype.getMouseProjectionOnBall = function( clientX, clientY ) {
174205

175-
var mouse = new THREE.Vector3(
206+
var mouseOnBall = new THREE.Vector3(
176207
( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius,
177208
( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius,
178209
0.0
179210
);
180211

181-
var length = mouse.length();
212+
var length = mouseOnBall.length();
182213

183214
if ( length > 1.0 ) {
184215

185-
mouse.divideScalar( length );
216+
mouseOnBall.normalize();
186217

187218
} else {
188219

189-
mouse.z = Math.sqrt( 1.0 - length * length );
220+
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
190221

191222
}
192223

193-
var projection = this.up.clone().setLength( mouse.y );
194-
projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouse.x ) );
195-
projection.addSelf( this.position.clone().setLength( mouse.z ) );
224+
var projection = this.up.clone().setLength( mouseOnBall.y );
225+
projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouseOnBall.x ) );
226+
projection.addSelf( this.position.clone().setLength( mouseOnBall.z ) );
196227

197228
return projection;
198229

199230
};
231+
232+
THREE.TrackballCamera.prototype.rotateCamera = function( clientX, clientY ) {
233+
234+
this.end = this.getMouseProjectionOnBall( clientX, clientY );
235+
236+
var angle = Math.acos( this.start.dot( this.end ) / this.start.length() / this.end.length() );
237+
238+
if ( angle ) {
239+
240+
var axis = (new THREE.Vector3()).cross( this.end, this.start ).normalize(),
241+
quaternion = new THREE.Quaternion();
242+
243+
quaternion.setFromAxisAngle( axis, angle );
244+
245+
quaternion.multiplyVector3( this.position );
246+
quaternion.multiplyVector3( this.up );
247+
248+
}
249+
250+
};
251+
252+
THREE.TrackballCamera.prototype.zoomCamera = function( clientX, clientY ) {
253+
254+
var newMouse = this.getMouseOnScreen( clientX, clientY ),
255+
eye = this.position.clone().subSelf( this.target.position ),
256+
factor = 1.0 + ( newMouse.y - this.mouse.y ) * this.zoomSpeed;
257+
258+
if ( factor > 0.0 ) {
259+
260+
this.position.add( this.target.position, eye.multiplyScalar( factor ) );
261+
this.mouse = newMouse;
262+
263+
}
264+
265+
};
266+
267+
THREE.TrackballCamera.prototype.panCamera = function( clientX, clientY ) {
268+
269+
var newMouse = this.getMouseOnScreen( clientX, clientY ),
270+
mouseChange = newMouse.clone().subSelf(this.mouse),
271+
factor = this.position.distanceTo( this.target.position ) * this.panSpeed;
272+
273+
mouseChange.multiplyScalar( factor );
274+
275+
var pan = this.position.clone().crossSelf( this.up ).setLength( mouseChange.x );
276+
pan.addSelf( this.up.clone().setLength( mouseChange.y ) );
277+
278+
this.position.addSelf(pan);
279+
this.target.position.addSelf(pan);
280+
281+
this.mouse = newMouse;
282+
283+
};

0 commit comments

Comments
 (0)