Skip to content

Commit ecfc809

Browse files
'Turntable' option for camera_mode? #446
1 parent 1e50d0b commit ecfc809

File tree

10 files changed

+115
-12
lines changed

10 files changed

+115
-12
lines changed

js/src/core/Core.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const msgpack = require('msgpack-lite');
33

44
const LilGUI = require('lil-gui').GUI;
55
const {viewModes} = require('./lib/viewMode');
6+
const {cameraUpAxisModes} = require('./lib/cameraUpAxis');
67
const _ = require('../lodash');
78
const {cameraModes} = require('./lib/cameraMode');
89
const loader = require('./lib/Loader');
@@ -14,6 +15,7 @@ const detachWindowGUI = require('./lib/detachWindow');
1415
const fullscreen = require('./lib/fullscreen');
1516
const {viewModeGUI} = require('./lib/viewMode');
1617
const {cameraModeGUI} = require('./lib/cameraMode');
18+
const {cameraUpAxisGUI} = require('./lib/cameraUpAxis');
1719
const manipulate = require('./lib/manipulate');
1820
const {getColorLegend} = require('./lib/colorMapLegend');
1921
const objectsGUIProvider = require('./lib/objectsGUIprovider');
@@ -132,6 +134,7 @@ function K3D(provider, targetDOMNode, parameters) {
132134

133135
viewModeGUI(GUI.controls, self);
134136
cameraModeGUI(GUI.controls, self);
137+
cameraUpAxisGUI(GUI.controls, self);
135138
manipulate.manipulateGUI(GUI.controls, self, changeParameters);
136139

137140
GUI.controls.add(self.parameters, 'cameraFov').step(0.1).min(1.0).max(179)
@@ -299,6 +302,7 @@ function K3D(provider, targetDOMNode, parameters) {
299302
cameraDampingFactor: 0.0,
300303
name: null,
301304
cameraFov: 60.0,
305+
cameraUpAxis: cameraUpAxisModes.none,
302306
cameraAnimation: {},
303307
autoRendering: true,
304308
axesHelper: 1.0,
@@ -722,14 +726,29 @@ function K3D(provider, targetDOMNode, parameters) {
722726
self.parameters.cameraDampingFactor = factor;
723727

724728
self.getWorld().changeControls(true);
729+
};
730+
731+
/**
732+
* Set camera up axis
733+
* @memberof K3D.Core
734+
* @param {String} axis
735+
*/
736+
this.setCameraUpAxis = function (axis) {
737+
self.parameters.cameraUpAxis = axis;
738+
739+
self.getWorld().changeControls(true);
725740

726741
if (GUI.controls) {
727742
GUI.controls.controllers.forEach((controller) => {
728-
if (controller.property === 'damping_factor') {
743+
if (controller.property === 'cameraUpAxis') {
729744
controller.updateDisplay();
730745
}
731746
});
732747
}
748+
749+
self.rebuildSceneData(false).then(() => {
750+
self.render();
751+
});
733752
};
734753

735754
/**
@@ -1268,6 +1287,7 @@ function K3D(provider, targetDOMNode, parameters) {
12681287
self.setGrid(self.parameters.grid);
12691288
self.setCameraAutoFit(self.parameters.cameraAutoFit);
12701289
self.setCameraDampingFactor(self.parameters.cameraDampingFactor);
1290+
self.setCameraUpAxis(self.parameters.cameraUpAxis);
12711291
self.setClippingPlanes(self.parameters.clippingPlanes);
12721292
self.setDirectionalLightingIntensity(self.parameters.lighting);
12731293
self.setColorMapLegend(self.parameters.colorbarObjectId);

js/src/core/lib/cameraUpAxis.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const cameraUpAxisModes = {
2+
x: 'x',
3+
y: 'y',
4+
z: 'z',
5+
none: 'none'
6+
};
7+
8+
function cameraUpAxisGUI(gui, K3D) {
9+
gui.add(K3D.parameters, 'cameraUpAxis', {
10+
x: cameraUpAxisModes.x,
11+
y: cameraUpAxisModes.y,
12+
z: cameraUpAxisModes.z,
13+
none: cameraUpAxisModes.none
14+
}).name('CameraUpAxis').onChange(
15+
(axis) => {
16+
K3D.setCameraUpAxis(axis);
17+
18+
K3D.dispatch(K3D.events.PARAMETERS_CHANGE, {
19+
key: 'camera_up_axis',
20+
value: axis
21+
});
22+
},
23+
);
24+
}
25+
26+
function setupUpVector(camera, cameraUpAxis) {
27+
if (cameraUpAxis === cameraUpAxisModes.x) {
28+
camera.up.set(1, 0, 0);
29+
} else if (cameraUpAxis === cameraUpAxisModes.y) {
30+
camera.up.set(0, 1, 0);
31+
} else if (cameraUpAxis === cameraUpAxisModes.z) {
32+
camera.up.set(0, 0, 1);
33+
}
34+
}
35+
36+
module.exports = {
37+
cameraUpAxisGUI,
38+
cameraUpAxisModes,
39+
setupUpVector
40+
};

js/src/k3d.js

+6
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ class PlotView extends widgets.DOMWidgetView {
310310
this.model.on('change:camera_pan_speed', this._setCameraSpeeds, this);
311311
this.model.on('change:camera_fov', this._setCameraFOV, this);
312312
this.model.on('change:camera_damping_factor', this._setCameraDampingFactor, this);
313+
this.model.on('change:camera_up_axis', this._setCameraUpAxis, this);
313314
this.model.on('change:axes_helper', this._setAxesHelper, this);
314315
this.model.on('change:axes_helper_colors', this._setAxesHelperColors, this);
315316
this.model.on('change:snapshot_type', this._setSnapshotType, this);
@@ -338,6 +339,7 @@ class PlotView extends widgets.DOMWidgetView {
338339
cameraPanSpeed: this.model.get('camera_pan_speed'),
339340
cameraDampingFactor: this.model.get('camera_damping_factor'),
340341
cameraFov: this.model.get('camera_fov'),
342+
cameraUpAxis: this.model.get('camera_up_axis'),
341343
colorbarObjectId: this.model.get('colorbar_object_id'),
342344
cameraAnimation: this.model.get('camera_animation'),
343345
name: this.model.get('name'),
@@ -563,6 +565,10 @@ class PlotView extends widgets.DOMWidgetView {
563565
this.K3DInstance.setCameraDampingFactor(this.model.get('camera_damping_factor'));
564566
};
565567

568+
_setCameraUpAxis() {
569+
this.K3DInstance.setCameraUpAxis(this.model.get('camera_up_axis'));
570+
};
571+
566572
_setClippingPlanes() {
567573
this.K3DInstance.setClippingPlanes(this.model.get('clipping_planes'));
568574
};

js/src/providers/threejs/helpers/THREE.OrbitControls.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
const { setupUpVector } = require('./../../../core/lib/cameraUpAxis');
2+
13
/* eslint-disable */
24
module.exports = function (THREE) {
3-
THREE.OrbitControls = function (object, domElement) {
5+
THREE.OrbitControls = function (object, domElement, K3D) {
46

57
if (domElement !== undefined) {
68
this.domElement = domElement;
@@ -144,10 +146,11 @@ module.exports = function (THREE) {
144146

145147
// this method is exposed, but perhaps it would be better if we can make it private...
146148
this.update = function (silent) {
147-
148149
const offset = new THREE.Vector3();
149150

150151
// so camera.up is the orbit axis
152+
setupUpVector(object, K3D.parameters.cameraUpAxis);
153+
151154
const quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
152155
const quatInverse = quat.clone().invert();
153156

js/src/providers/threejs/helpers/THREE.TrackballControls.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable */
2+
const { setupUpVector } = require('./../../../core/lib/cameraUpAxis');
23

34
module.exports = function (THREE) {
4-
THREE.TrackballControls = function (object, domElement) {
5+
THREE.TrackballControls = function (object, domElement, K3D) {
56
const scope = this;
67
const STATE = {
78
NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4,
@@ -46,7 +47,7 @@ module.exports = function (THREE) {
4647
this.minDistance = 0;
4748
this.maxDistance = Infinity;
4849

49-
this.mouseButtons = {LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN};
50+
this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN };
5051

5152
// internals
5253

@@ -91,9 +92,9 @@ module.exports = function (THREE) {
9192

9293
// events
9394

94-
const _changeEvent = {type: 'change'};
95-
const _startEvent = {type: 'start'};
96-
const _endEvent = {type: 'end'};
95+
const _changeEvent = { type: 'change' };
96+
const _startEvent = { type: 'start' };
97+
const _endEvent = { type: 'end' };
9798

9899
// methods
99100

@@ -292,6 +293,8 @@ module.exports = function (THREE) {
292293
};
293294

294295
this.update = function (silent) {
296+
setupUpVector(scope.object, K3D.parameters.cameraUpAxis);
297+
295298
_eye.subVectors(scope.object.position, scope.target);
296299

297300
if (!scope.noRotate) {
@@ -648,7 +651,7 @@ module.exports = function (THREE) {
648651

649652
this.domElement.addEventListener('pointerdown', onPointerDown);
650653
this.domElement.addEventListener('pointercancel', onPointerCancel);
651-
this.domElement.addEventListener('wheel', onMouseWheel, {passive: false});
654+
this.domElement.addEventListener('wheel', onMouseWheel, { passive: false });
652655
this.domElement.addEventListener('contextmenu', contextmenu);
653656

654657
currentDocument.addEventListener('keydown', keydown);

js/src/providers/threejs/initializers/Camera.js

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module.exports = function (K3D) {
4040

4141
if (array.length === 9) {
4242
this.controls.object.up.fromArray(array, 6);
43+
this.axesHelper.camera.up.copy(this.controls.object.up);
4344
}
4445

4546
this.controls.target.fromArray(array, 3);

js/src/providers/threejs/initializers/Canvas.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function addEvents(self, K3D, controls) {
3434
}
3535

3636
function createTrackballControls(self, K3D) {
37-
const controls = new THREE.TrackballControls(self.camera, self.renderer.domElement);
37+
const controls = new THREE.TrackballControls(self.camera, self.renderer.domElement, K3D);
3838

3939
controls.type = cameraModes.trackball;
4040
controls.rotateSpeed = K3D.parameters.cameraRotateSpeed;
@@ -54,7 +54,7 @@ function createTrackballControls(self, K3D) {
5454
}
5555

5656
function createOrbitControls(self, K3D) {
57-
const controls = new THREE.OrbitControls(self.camera, self.renderer.domElement);
57+
const controls = new THREE.OrbitControls(self.camera, self.renderer.domElement, K3D);
5858

5959
controls.type = cameraModes.orbit;
6060
controls.rotateSpeed = K3D.parameters.cameraRotateSpeed;

k3d/factory.py

+14
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,7 @@ def plot(
20582058
camera_zoom_speed=1.2,
20592059
camera_pan_speed=0.3,
20602060
camera_damping_factor=0.0,
2061+
camera_up_axis='none',
20612062
fps=25.0,
20622063
minimum_fps=-1,
20632064
fps_meter=False,
@@ -2130,6 +2131,18 @@ def plot(
21302131
Camera pan speed, by default 0.3.
21312132
camera_damping_factor : float, optional
21322133
Camera intensity of damping, by default 0.0.
2134+
camera_up_axis: `str`.
2135+
Fixed up axis for camera.
2136+
2137+
Legal values are:
2138+
2139+
:`x`: x axis,
2140+
2141+
:`y`: y axis,
2142+
2143+
:`z`: z axis,
2144+
2145+
:`none`: Handling click_callback and hover_callback on some type of objects.
21332146
fps : float, optional
21342147
Animations FPS, by default 25.0.
21352148
minimum_fps: `Float`.
@@ -2173,6 +2186,7 @@ def plot(
21732186
camera_zoom_speed=camera_zoom_speed,
21742187
camera_damping_factor=camera_damping_factor,
21752188
camera_pan_speed=camera_pan_speed,
2189+
camera_up_axis=camera_up_axis,
21762190
auto_rendering=auto_rendering,
21772191
fps=fps,
21782192
minimum_fps=minimum_fps,

k3d/plot.py

+16
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ class Plot(widgets.DOMWidget):
6060
Camera Field of View.
6161
camera_damping_factor: `Float`.
6262
Defines the intensity of damping. Default is 0 (disabled).
63+
camera_up_axis: `str`.
64+
Fixed up axis for camera.
65+
66+
Legal values are:
67+
68+
:`x`: x axis,
69+
70+
:`y`: y axis,
71+
72+
:`z`: z axis,
73+
74+
:`none`: Handling click_callback and hover_callback on some type of objects.
6375
snapshot_type: `string`.
6476
Can be 'full', 'online' or 'inline'.
6577
axes: `list`.
@@ -159,6 +171,7 @@ class Plot(widgets.DOMWidget):
159171
camera_zoom_speed = Float().tag(sync=True)
160172
camera_pan_speed = Float().tag(sync=True)
161173
camera_damping_factor = Float().tag(sync=True)
174+
camera_up_axis = Unicode().tag(sync=True)
162175
clipping_planes = ListOrArray(empty_ok=True).tag(sync=True)
163176
colorbar_object_id = Int(-1).tag(sync=True)
164177
colorbar_scientific = Bool(False).tag(sync=True)
@@ -203,6 +216,7 @@ def __init__(
203216
camera_rotate_speed=1.0,
204217
camera_zoom_speed=1.2,
205218
camera_pan_speed=0.3,
219+
camera_up_axis='none',
206220
snapshot_type='full',
207221
camera_no_pan=False,
208222
camera_fov=45.0,
@@ -252,6 +266,7 @@ def __init__(
252266
self.camera_pan_speed = camera_pan_speed
253267
self.camera_damping_factor = camera_damping_factor
254268
self.camera_fov = camera_fov
269+
self.camera_up_axis = camera_up_axis
255270
self.axes = axes
256271
self.axes_helper = axes_helper
257272
self.axes_helper_colors = axes_helper_colors
@@ -498,6 +513,7 @@ def get_plot_params(self):
498513
"cameraZoomSpeed": self.camera_zoom_speed,
499514
"cameraPanSpeed": self.camera_pan_speed,
500515
"cameraDampingFactor": self.camera_damping_factor,
516+
"cameraUpAxis": self.camera_up_axis,
501517
"name": self.name,
502518
"height": self.height,
503519
"cameraFov": self.camera_fov,

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "k3d",
3-
"version": "2.16.0",
3+
"version": "2.17.0",
44
"description": "3D visualization library",
55
"keywords": [
66
"jupyter",

0 commit comments

Comments
 (0)