Skip to content

Commit ba53d44

Browse files
authored
Merge pull request #122 from vidartf/fix-fly
Fix FlyControls
2 parents a75bd90 + 69c1bd6 commit ba53d44

File tree

5 files changed

+91
-102
lines changed

5 files changed

+91
-102
lines changed

js/scripts/three-class-config.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,11 @@ module.exports = {
239239
relativePath: './controls/FlyControls',
240240
superClass: 'Controls',
241241
properties: {
242-
forward_speed: new Types.Float(0),
243-
lateral_speed: new Types.Float(0),
244-
upward_speed: new Types.Float(0),
245-
roll: new Types.Float(0),
246-
pitch: new Types.Float(0),
247-
yaw: new Types.Float(0),
242+
moveVector: new Types.Vector3(0, 0, 0),
243+
rotationVector: new Types.Vector3(0, 0, 0),
244+
movementSpeed: new Types.Float(1.0),
245+
rollSpeed: new Types.Float(0.05),
246+
syncRate: new Types.Float(1.0),
248247
},
249248
},
250249
Picker: {

js/src/_base/Preview.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ var PreviewView = RenderableView.extend({
3434
setupEventListeners: function() {
3535
RenderableView.prototype.setupEventListeners.call(this);
3636
var child = this.model.get('child');
37-
this.listenTo(child, 'change', this.onChildChange.bind(this));
37+
this.listenTo(child, 'change', this.onChildChanged.bind(this));
3838
if (child.obj.isObject3D) {
3939
// Since we use clone for objects, we need to rebuild for
4040
// any nested change instead of just rerendering.
41-
this.listenTo(child, 'childchange', this.onChildChange.bind(this));
41+
this.listenTo(child, 'childchange', this.onChildChanged.bind(this));
4242
}
4343
},
4444

45-
onChildChange: function() {
45+
onChildChanged: function() {
4646
// Enabling this line will reset the camera
4747
// when any changes are made to the child
4848
//this._resetCameraNeeded = true;
@@ -257,11 +257,11 @@ var PreviewModel = RenderableModel.extend({
257257

258258
setupListeners: function() {
259259
var child = this.get('child');
260-
this.listenTo(child, 'change', this.onChildChange.bind(this));
261-
this.listenTo(child, 'childchange', this.onChildChange.bind(this));
260+
this.listenTo(child, 'change', this.onChildChanged.bind(this));
261+
this.listenTo(child, 'childchange', this.onChildChanged.bind(this));
262262
},
263263

264-
onChildChange: function(model, options) {
264+
onChildChanged: function(model, options) {
265265
this.trigger('rerender', this, {});
266266
},
267267

js/src/controls/FlyControls.js

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,58 @@
11
var _ = require('underscore');
22
var THREE = require('three');
3+
var widgets = require('@jupyter-widgets/base');
34
var FlyControls = require("../examples/controls/MomentumCameraControls.js").FlyControls;
45
var FlyControlsAutogen = require('./FlyControls.autogen');
56

67

78
var FlyControlsModel = FlyControlsAutogen.FlyControlsModel.extend({
89

910
constructThreeObject: function() {
10-
var that = this;
1111
this.clock = new THREE.Clock();
12+
var controlling = this.get('controlling');
13+
this.renderer = null;
14+
this.syncAtWill = true;
15+
16+
obj = new FlyControls(controlling.obj);
17+
obj.dispose(); // Disconnect events, we need to (dis-)connect on freeze/thaw
18+
return obj
19+
},
20+
21+
setupListeners: function() {
22+
FlyControlsAutogen.FlyControlsModel.prototype.setupListeners.call(this);
23+
var that = this;
24+
this.obj.addEventListener('change', function() {
25+
// Throttle syncs:
26+
if (that.syncAtWill) {
27+
that.syncAtWill = false;
28+
that.update_controlled();
29+
setTimeout(that.allowSync.bind(that), 1000 * that.get('syncRate'));
30+
}
31+
});
32+
this.on('enableControl', this.onEnable, this);
33+
this.on('disableControl', this.onDisable, this);
34+
},
35+
36+
onEnable: function(renderer) {
37+
this.clock.start();
38+
this.renderer = renderer;
39+
this._update();
40+
},
1241

13-
return widgets.resolvePromisesDict(this.model.get('controlling').views).then(function(views) {
14-
// get the view that is tied to the same renderer
15-
that.controlled_view = _.find(views, function(o) {
16-
return o.options.renderer_id === that.options.renderer_id
17-
}, that);
18-
obj = new FlyControls(that.controlled_view.obj, that.options.dom);
19-
that.register_object_parameters();
20-
that.options.register_update(that._update, that);
21-
obj.addEventListener('change', that.options.render_frame);
22-
obj.addEventListener('change', function() { that.update_controlled(); });
23-
that.options.start_update_loop();
24-
that.model.on_some_change(['forward_speed', 'upward_speed', 'lateral_speed',
25-
'roll', 'yaw', 'pitch'], that.update_plane, that);
26-
delete that.options.renderer;
27-
return obj
28-
});
42+
onDisable: function(renderer) {
43+
this.clock.stop();
44+
this.renderer = null;
2945
},
3046

31-
update_plane: function() {
32-
this.obj.moveState.back = this.model.get('forward_speed');
33-
this.obj.moveState.up = this.model.get('upward_speed');
34-
this.obj.moveState.left = this.model.get('lateral_speed');
35-
this.obj.moveState.pitchUp = this.model.get('pitch');
36-
this.obj.moveState.yawRight = this.model.get('yaw');
37-
this.obj.moveState.rollLeft = this.model.get('roll');
38-
this.obj.updateRotationVector();
39-
this.obj.updateMovementVector();
47+
allowSync: function() {
48+
this.syncAtWill = true;
4049
},
4150

4251
_update: function() {
43-
this.obj.movementSpeed = 0.33;
44-
this.obj.update(this.clock.getDelta());
52+
if (this.renderer !== null) {
53+
this.obj.update(this.clock.getDelta());
54+
requestAnimationFrame(this._update.bind(this));
55+
}
4556
},
4657

4758
update_controlled: function() {

js/src/core/Renderer.js

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ var ThreeModel = require('../_base/Three').ThreeModel;
1212

1313
var RendererModel = RenderableModel.extend({
1414

15-
defaults: _.extend({}, RenderableModel.prototype.defaults, {
16-
17-
_view_name: 'RendererView',
18-
_model_name: 'RendererModel',
19-
20-
scene: null,
21-
camera: null,
22-
controls: [],
23-
effect: null,
24-
background: "black",
25-
background_opacity: 1.0,
26-
27-
}),
15+
defaults: function() {
16+
return _.extend(RenderableModel.prototype.defaults.call(this), {
17+
18+
_view_name: 'RendererView',
19+
_model_name: 'RendererModel',
20+
21+
scene: null,
22+
camera: null,
23+
controls: [],
24+
effect: null,
25+
background: "black",
26+
background_opacity: 1.0,
27+
});
28+
},
2829

2930
initialize: function(attributes, options) {
3031
RenderableModel.prototype.initialize.apply(this, arguments);
@@ -38,18 +39,18 @@ var RendererModel = RenderableModel.extend({
3839

3940
var scene = this.get('scene');
4041
var camera = this.get('camera');
41-
this.listenTo(scene, 'change', this.onChildChange.bind(this));
42-
this.listenTo(scene, 'childchange', this.onChildChange.bind(this));
43-
this.listenTo(scene, 'rerender', this.onChildChange.bind(this));
42+
this.listenTo(scene, 'change', this.onChildChanged.bind(this));
43+
this.listenTo(scene, 'childchange', this.onChildChanged.bind(this));
44+
this.listenTo(scene, 'rerender', this.onChildChanged.bind(this));
4445
this.listenTo(camera, 'change', this.onCameraChange.bind(this));
4546

4647
},
4748

4849
onCameraChange: function(model, options) {
49-
this.onChildChange();
50+
this.onChildChanged(model, options);
5051
},
5152

52-
onChildChange: function(model, options) {
53+
onChildChanged: function(model, options) {
5354
this.trigger('rerender', this, {});
5455
},
5556

js/src/examples/controls/MomentumCameraControls.js

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,28 @@ var FlyControls = function ( object, domElement ) {
99
this.object = object;
1010

1111
this.domElement = ( domElement !== undefined ) ? domElement : document;
12-
if ( domElement ) this.domElement.setAttribute( 'tabindex', -1 );
1312

1413
// API
1514

15+
// Set to false to disable this control
16+
this.enabled = true;
17+
1618
this.movementSpeed = 1.0;
1719
this.rollSpeed = 0.05;
1820

19-
this.dragToLook = false;
20-
this.autoForward = false;
21-
22-
// disable default target object behavior
21+
this.moveVector = new THREE.Vector3( 0, 0, 0 );
22+
this.rotationVector = new THREE.Vector3( 0, 0, 0 );
2323

2424
// internals
2525

2626
this.tmpQuaternion = new THREE.Quaternion();
2727
var lastPosition = new THREE.Vector3();
2828
var lastQuaternion = new THREE.Quaternion();
29-
var scope = this;
29+
var scope = this;
30+
var EPS = 0.000001;
3031

3132
this.mouseStatus = 0;
3233

33-
this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 };
34-
this.moveVector = new THREE.Vector3( 0, 0, 0 );
35-
this.rotationVector = new THREE.Vector3( 0, 0, 0 );
36-
3734
this.handleEvent = function ( event ) {
3835
if ( typeof this[ event.type ] == 'function' ) {
3936
this[ event.type ]( event );
@@ -45,48 +42,30 @@ var FlyControls = function ( object, domElement ) {
4542
var moveMult = delta * this.movementSpeed;
4643
var rotMult = delta * this.rollSpeed;
4744

48-
this.object.translateX( this.moveVector.x * moveMult );
49-
this.object.translateY( this.moveVector.y * moveMult );
50-
this.object.translateZ( this.moveVector.z * moveMult );
45+
this.object.position.addScaledVector(this.moveVector, moveMult);
5146

5247
this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();
5348
this.object.quaternion.multiply( this.tmpQuaternion );
5449

5550
// expose the rotation vector for convenience
5651
this.object.rotation.setFromQuaternion( this.object.quaternion, this.object.rotation.order );
57-
this.dispatchEvent( changeEvent );
58-
lastPosition.copy( this.object.position );
59-
lastQuaternion.copy( this.object.position );
60-
};
52+
if (lastPosition.distanceToSquared( this.object.position ) > EPS ||
53+
8 * ( 1 - lastQuaternion.dot( this.object.quaternion ) ) > EPS ) {
6154

62-
this.updateMovementVector = function() {
63-
this.moveVector.x = ( -this.moveState.left + this.moveState.right );
64-
this.moveVector.y = ( -this.moveState.down + this.moveState.up );
65-
this.moveVector.z = ( -this.moveState.forward + this.moveState.back );
66-
};
67-
68-
this.updateRotationVector = function() {
69-
this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp );
70-
this.rotationVector.y = ( -this.moveState.yawRight + this.moveState.yawLeft );
71-
this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft );
72-
};
73-
74-
this.getContainerDimensions = function() {
75-
if ( this.domElement != document ) {
76-
return {
77-
size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ],
78-
offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ]
79-
};
80-
} else {
81-
return {
82-
size : [ window.innerWidth, window.innerHeight ],
83-
offset : [ 0, 0 ]
84-
};
55+
this.dispatchEvent( changeEvent );
56+
lastPosition.copy( this.object.position );
57+
lastQuaternion.copy( this.object.quaternion );
58+
return true;
8559
}
60+
return false;
8661
};
8762

8863
this.dispose = function() {};
89-
this.connectEvents = function() {};
64+
this.connectEvents = function(element) {
65+
if (element) {
66+
scope.domElement = element;
67+
}
68+
};
9069

9170
function bind( scope, fn ) {
9271
return function () {
@@ -98,9 +77,8 @@ var FlyControls = function ( object, domElement ) {
9877

9978
var changeEvent = { type: 'change' };
10079

101-
this.updateMovementVector();
102-
this.updateRotationVector();
103-
80+
// Initialize lastPosition/Quaternion to initial values.
81+
this.update(0);
10482
};
10583

10684
FlyControls.prototype = Object.create( THREE.EventDispatcher.prototype );

0 commit comments

Comments
 (0)