@ -1,5 +1,7 @@
package visualiser.layout ;
import javafx.beans.value.ChangeListener ;
import javafx.beans.value.ObservableValue ;
import javafx.collections.ListChangeListener ;
import javafx.collections.ObservableList ;
import javafx.geometry.Point3D ;
@ -31,6 +33,10 @@ public class View3D extends Pane {
* Map for selecting Subject3D from Shape3D
* /
private Map < Shape3D , Subject3D > selectionMap ;
/ * *
* Subject tracked by camera
* /
private Subject3D target ;
/ * *
* Rendering container for shapes
* /
@ -60,12 +66,23 @@ public class View3D extends Pane {
* /
private Rotate pitch ;
private ChangeListener < ? super Number > pivotHeading = ( o , prev , curr ) - > yaw . setAngle ( ( double ) curr ) ;
private ChangeListener < ? super Number > pivotX = ( o , prev , curr ) - > pivot . setX ( ( double ) curr ) ;
private ChangeListener < ? super Number > pivotY = ( o , prev , curr ) - > pivot . setY ( ( double ) curr ) ;
private ChangeListener < ? super Number > pivotZ = ( o , prev , curr ) - > pivot . setZ ( ( double ) curr ) ;
private double THIRD_PERSON_LIMIT = 100 ;
/ * *
* Default constructor for View3D . Sets up Scene and PerspectiveCamera .
* /
public View3D ( ) {
world = new Group ( ) ;
selectionMap = new HashMap < > ( ) ;
target = null ;
SubScene scene = new SubScene ( world , 300 , 300 ) ;
scene . widthProperty ( ) . bind ( this . widthProperty ( ) ) ;
@ -77,14 +94,7 @@ public class View3D extends Pane {
scene . setOnMousePressed ( e - > {
PickResult result = e . getPickResult ( ) ;
if ( result ! = null & & result . getIntersectedNode ( ) ! = null & & result . getIntersectedNode ( ) instanceof Shape3D ) {
Subject3D target = selectionMap . get ( result . getIntersectedNode ( ) ) ;
target . getPosition ( ) . xProperty ( ) . addListener ( ( o , prev , curr ) - > pivot . setX ( ( double ) curr ) ) ;
target . getPosition ( ) . yProperty ( ) . addListener ( ( o , prev , curr ) - > pivot . setY ( ( double ) curr ) ) ;
target . getPosition ( ) . zProperty ( ) . addListener ( ( o , prev , curr ) - > pivot . setZ ( ( double ) curr ) ) ;
target . getHeading ( ) . angleProperty ( ) . addListener ( ( o , prev , curr ) - > setYaw ( ( double ) curr ) ) ;
this . setDistance ( 100 ) ;
this . setPitch ( 30 ) ;
trackSubject ( selectionMap . get ( result . getIntersectedNode ( ) ) ) ;
}
} ) ;
@ -132,6 +142,31 @@ public class View3D extends Pane {
} ) ;
}
private void untrackSubject ( ) {
if ( target ! = null ) {
target . getPosition ( ) . xProperty ( ) . removeListener ( pivotX ) ;
target . getPosition ( ) . yProperty ( ) . removeListener ( pivotY ) ;
target . getPosition ( ) . zProperty ( ) . removeListener ( pivotZ ) ;
target . getHeading ( ) . angleProperty ( ) . removeListener ( pivotHeading ) ;
}
}
private void trackSubject ( Subject3D subject ) {
untrackSubject ( ) ;
target = subject ;
updatePivot ( target . getPosition ( ) ) ;
setYaw ( target . getHeading ( ) . getAngle ( ) ) ;
target . getPosition ( ) . xProperty ( ) . addListener ( pivotX ) ;
target . getPosition ( ) . yProperty ( ) . addListener ( pivotY ) ;
target . getPosition ( ) . zProperty ( ) . addListener ( pivotZ ) ;
target . getHeading ( ) . angleProperty ( ) . addListener ( pivotHeading ) ;
this . setDistance ( THIRD_PERSON_LIMIT ) ;
this . setPitch ( 20 ) ;
}
public void setNearClip ( double nearClip ) {
this . nearClip = nearClip ;
}
@ -155,7 +190,18 @@ public class View3D extends Pane {
}
public void updateDistance ( double delta ) {
this . distance . setZ ( this . distance . getZ ( ) - delta ) ;
double distance = - this . distance . getZ ( ) + delta ;
if ( distance < = 0 ) {
this . setDistance ( 0 ) ;
} else if ( distance > THIRD_PERSON_LIMIT ) {
untrackSubject ( ) ;
this . setYaw ( 0 ) ;
this . setPitch ( 60 ) ;
this . setDistance ( distance ) ;
} else {
this . setDistance ( distance ) ;
}
}
/ * *