aw-think
aw-think

Reputation: 4803

Can't add JavaFX lights to multiple SubScenes

Problem

In JavaFX is a default light on every 3D Scene. It's a PointLight shining from top of Scene.

I've tried to show in my program the different possibilities of light, but I ran in trouble. If I only add a SubScene with default, PointLight and AmbientLight, everything works as aspected. But if I then add one more SubScene with a combined Light of Ambient and Point, I'll get the result showing in Screenshot 2. It seems all other SubScene lost their light and fall back to it's default light. Maybe I hit a bug?

Systems tested

Stage with 3 SubScenes - Default, Point, Ambient

3Lights

Stage with 4 SubScenes - Default, Point, Ambient, (Point,Ambient)

4Lights

Example

Here is a Minimal, Complete, and Verifiable example

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*;
import javafx.stage.Stage;

public class Shapes3DViewer extends Application {

  PhongMaterial material;

  @Override
  public void start(Stage stage) {
    material = new PhongMaterial();
    material.setDiffuseColor(Color.FIREBRICK);
    material.setSpecularColor(Color.YELLOW);

    PointLight pointLight = new PointLight(Color.WHITE);
    pointLight.setTranslateX(100);
    pointLight.setTranslateY(100);
    pointLight.setTranslateZ(-300);
    pointLight.setRotate(90);

    AmbientLight ambient = new AmbientLight();

    Group g1 = createSphereGroup(100, "Default light");
    Group g2 = createSphereGroup(100, "Point light");
    Group g3 = createSphereGroup(100, "Ambient light");
    Group g4 = createSphereGroup(100, "Ambient & Point light");

    g2.getChildren().add(pointLight);
    g3.getChildren().add(ambient);
    g4.getChildren().addAll(pointLight, ambient);

    SubScene s1 = createSubScene(g1, 400, 400);
    SubScene s2 = createSubScene(g2, 400, 400);
    SubScene s3 = createSubScene(g3, 400, 400);
    SubScene s4 = createSubScene(g4, 400, 400);

    HBox root = new HBox();
    root.getChildren().addAll(s1, s2, s3, s4);

    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.show();
  }

  public static void main(String[] args) {
    launch(args);
  }

  private Group createSphereGroup(double radius, String text) {
    Sphere c = new Sphere(radius);
    c.setMaterial(material);
    c.setDrawMode(DrawMode.FILL);
    c.setTranslateX(radius * 1.33);
    c.setTranslateY(radius * 2);
    Label lbl = new Label(text);
    lbl.setStyle("-fx-text-fill: red;-fx-font-size: 18pt;");
    return new Group(c, lbl);
  }

  private SubScene createSubScene(Group group, double width, double height) {
    SubScene s = new SubScene(group, width, height);
    s.setCamera(new PerspectiveCamera());
    s.setFill(Color.color(.1, .1, .1));
    return s;
  }
}

Output of MCVE on:

javafx.runtime.version=8.0.45-b11
OS X 10.9.5
2014 Macbook Pro

mac test

Question

Am I doing wrong, or is this a bug? Can someone confirm the same behaviour?

Update

I've made a new test where I added two new lights: pointLight2 and ambient2. That both I've added to the fourth sphere. This solution works.

PointLight pointLight2 = new PointLight(Color.WHITE);
    pointLight.setTranslateX(100);
    pointLight.setTranslateY(100);
    pointLight.setTranslateZ(-300);
    pointLight.setRotate(90);

AmbientLight ambient2 = new AmbientLight();

g4.getChildren().addAll(pointLight2, ambient2);

4Lights-new

It seems that the lights will be merged and only added to one Scene and removed from all other scenes.

Conclusion

As jewselsea explained in his answer, this is not a bug! But from my point of view they should repeat that statement in the Light Classes again or make a hint, because it's a little bit confusing.

SubScene needs a Parent as root in his constructor, so you don't have a choice.

Upvotes: 4

Views: 1945

Answers (1)

jewelsea
jewelsea

Reputation: 159436

This is not a bug. A PointLight is a Node. Node javadoc states: "If a program adds a child node to a Parent (including Group, Region, etc) and that node is already a child of a different Parent or the root of a Scene, the node is automatically (and silently) removed from its former parent." So the application appears to be behaving as expected.

Upvotes: 3

Related Questions