Skip to content

Commit 6692ab0

Browse files
authored
Merge pull request #19 from martinRenou/camera_position_synchronisation
Allow modifying camera position
2 parents 04c5034 + 3a5b2c6 commit 6692ab0

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

ipygany/ipygany.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,10 @@ class Scene(_GanyDOMWidgetBase):
650650
background_color = Color('white').tag(sync=True)
651651
background_opacity = CFloat(1.).tag(sync=True)
652652

653+
camera_position = Union((Tuple(trait=CFloat, minlen=3, maxlen=3), ), allow_none=True, default_value=None).tag(sync=True)
654+
camera_target = Union((Tuple(trait=CFloat, minlen=3, maxlen=3), ), allow_none=True, default_value=None).tag(sync=True)
655+
camera_up = Tuple(trait=CFloat, minlen=3, maxlen=3, default_value=(0, 1, 0)).tag(sync=True)
656+
653657
def __init__(self, children=[], **kwargs):
654658
"""Construct a Scene."""
655659
super(Scene, self).__init__(children=children, **kwargs)

src/widget.ts

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,9 @@ class SceneModel extends _GanyDOMWidgetModel {
786786
background_color: 'white',
787787
background_opacity: 1.,
788788
children: [],
789+
camera_position: null,
790+
camera_up: [0, 1, 0],
791+
camera_target: null,
789792
};
790793
}
791794

@@ -794,6 +797,10 @@ class SceneModel extends _GanyDOMWidgetModel {
794797

795798
this.scene = new Scene();
796799

800+
this._scale = new THREE.Vector3(1., 1., 1.);
801+
this._translation = new THREE.Vector3(0., 0., 0.);
802+
this.updateMatrix();
803+
797804
this.updateChildren();
798805
this.on('change:children', this.updateChildren.bind(this));
799806
}
@@ -806,6 +813,42 @@ class SceneModel extends _GanyDOMWidgetModel {
806813
return this.get('background_opacity')
807814
}
808815

816+
get cameraPosition () : THREE.Vector3 | null {
817+
const position = this.get('camera_position');
818+
819+
if (position === null) {
820+
return null;
821+
}
822+
823+
return this.scale(new THREE.Vector3(position[0], position[1], position[2]));
824+
}
825+
826+
get cameraUp () : THREE.Vector3 {
827+
const position = this.get('camera_up');
828+
return new THREE.Vector3(position[0], position[1], position[2]);
829+
}
830+
831+
get cameraTarget () : THREE.Vector3 | null {
832+
const target = this.get('camera_target');
833+
834+
if (target === null) {
835+
return null;
836+
}
837+
838+
return this.scale(new THREE.Vector3(target[0], target[1], target[2]));
839+
}
840+
841+
private scale (vector: THREE.Vector3) {
842+
return new THREE.Vector3().copy(vector).applyMatrix4(this._matrix);
843+
}
844+
845+
private updateMatrix () {
846+
const scaleMatrix = new THREE.Matrix4().makeScale(this._scale.x, this._scale.y, this._scale.z);
847+
const positionMatrix = new THREE.Matrix4().makeTranslation(this._translation.x, this._translation.y, this._translation.z);
848+
849+
this._matrix = new THREE.Matrix4().multiplyMatrices(scaleMatrix, positionMatrix);
850+
}
851+
809852
private updateChildren () {
810853
// TODO: Remove old children
811854

@@ -816,20 +859,32 @@ class SceneModel extends _GanyDOMWidgetModel {
816859
}
817860

818861
const boundingSphereRadius = Math.max(...blocks.map((block: Block) => block.boundingSphere.radius));
819-
const scale = new THREE.Vector3(1 / boundingSphereRadius, 1 / boundingSphereRadius, 1 / boundingSphereRadius);
862+
863+
const scale = 1 / boundingSphereRadius;
864+
this._scale.x = scale;
865+
this._scale.y = scale;
866+
this._scale.z = scale;
820867

821868
const position = blocks[0].boundingSphere.center;
822869

870+
this._translation = new THREE.Vector3(-position.x, -position.y, -position.z);
871+
872+
this.updateMatrix();
873+
823874
for (const block of blocks) {
824-
block.scale = scale;
825-
block.position = new THREE.Vector3(-position.x, -position.y, -position.z);
875+
block.scale = this._scale;
876+
block.position = this._translation;
826877

827878
this.scene.addBlock(block);
828879
}
829880
}
830881

831882
scene: Scene;
832883

884+
private _scale: THREE.Vector3;
885+
private _translation: THREE.Vector3;
886+
private _matrix: THREE.Matrix4;
887+
833888
static serializers: ISerializers = {
834889
..._GanyDOMWidgetModel.serializers,
835890
children: { deserialize: (unpack_models as any) },
@@ -854,6 +909,10 @@ class SceneView extends DOMWidgetView {
854909
this.renderer.backgroundColor = this.model.backgroundColor
855910
this.renderer.backgroundOpacity = this.model.backgroundOpacity;
856911

912+
this.updateCameraUp();
913+
this.updateCameraPosition();
914+
this.updateCameraTarget();
915+
857916
this.initEventListeners();
858917
});
859918
}
@@ -863,6 +922,34 @@ class SceneView extends DOMWidgetView {
863922

864923
this.model.on('change:background_color', () => { this.renderer.backgroundColor = this.model.backgroundColor; });
865924
this.model.on('change:background_opacity', () => { this.renderer.backgroundOpacity = this.model.backgroundOpacity; });
925+
926+
this.model.on('change:camera_position', this.updateCameraPosition.bind(this));
927+
this.model.on('change:camera_target', this.updateCameraTarget.bind(this));
928+
this.model.on('change:camera_up', this.updateCameraUp.bind(this));
929+
}
930+
931+
updateCameraPosition () {
932+
const newPosition = this.model.cameraPosition;
933+
934+
if (newPosition === null) {
935+
return;
936+
}
937+
938+
this.renderer.cameraPosition = newPosition;
939+
}
940+
941+
updateCameraTarget () {
942+
const newTarget = this.model.cameraTarget;
943+
944+
if (newTarget === null) {
945+
return;
946+
}
947+
948+
this.renderer.cameraTarget = newTarget;
949+
}
950+
951+
updateCameraUp () {
952+
this.renderer.cameraUp = this.model.cameraUp;
866953
}
867954

868955
processPhosphorMessage (msg: Message) {

0 commit comments

Comments
 (0)