set perspective camera as subscene camera in fxml file

58 Views Asked by At

In this code I have a Subscene with 3d features enabled. I add camera and meshviews at runtime, but I want to put the camera in FXML because I don´t need to change it at runtime. How can I do that ?

<SubScene fx:id="viewer3d" depthBuffer="true" fill="#3389de" height="600.0" width="600.0">
    <root>
        <Region />
    </root>
    <antiAliasing>
    <SceneAntialiasing fx:constant="BALANCED" />
1

There are 1 best solutions below

0
Slaw On BEST ANSWER

If you're okay with the fixedEyeAtCameraZero property being false then all you need is:

<camera>
  <!-- make sure to import the class (or use fully qualified name) -->
  <PerspectiveCamera/>
</camera>

Nested in the SubScene element.

However, if you want the aforementioned property to be true then unfortunately you have to write some code. Said property can only be set during construction, but the constructor does not annotate its parameter with @NamedArg. Meaning the following:

<camera>
  <PerspectiveCamera fixedEyeAtCameraZero="true"/>
</camera>

Will fail because the FXMLLoader will not know what to do with the attribute. In this case, there are two options:

  1. Instead of defining the camera in the FXML file, create the camera and set it on the sub-scene in code (e.g., in the controllers initialize method).

    I find this option preferable, but that is just my opinion.

  2. Continue defining the camera in the FXML file and implement a Builder and BuilderFactory.

    Here is an example implementation. Note the example Builder is extremely simple. It is only implemented to allow setting the fixedEyeAtCameraZero property. Trying to set any other property, which would have otherwise worked without registering this builder, will now fail. You can add other getters and setters as needed. Or, perhaps easier, you could have the builder implement Map<String, Object> and appropriately implement the put method.

    Builder

    import javafx.scene.PerspectiveCamera;
    import javafx.util.Builder;
    
    public class PerspectiveCameraBuilder implements Builder<PerspectiveCamera> {
    
      private boolean fixedEyeAtCameraZero;
    
      public boolean isFixedEyeAtCameraZero() {
        return fixedEyeAtCameraZero;
      }
    
      public void setFixedEyeAtCameraZero(boolean fixedEyeAtCameraZero) {
        this.fixedEyeAtCameraZero = fixedEyeAtCameraZero;
      }
    
      @Override
      public PerspectiveCamera build() {
        return new PerspectiveCamera(fixedEyeAtCameraZero);
      }
    }
    

    Builder Factory

    import javafx.scene.PerspectiveCamera;
    import javafx.util.Builder;
    import javafx.util.BuilderFactory;
    
    public class MyBuilderFactory implements BuilderFactory {
    
      @Override
      public Builder<?> getBuilder(Class<?> type) {
        if (type == PerspectiveCamera.class) {
          return new PerspectiveCameraBuilder();
        }
        return null;
      }
    }
    

    Usage

    var loader = new FXMLLoader(...);
    loader.setBuilderFactory(new MyBuilderFactory());
    // ... load FXML file