import java.nio.ByteBuffer; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javafx.application.Application; import javafx.beans.property.DoubleProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.scene.AmbientLight; import javafx.scene.Group; import javafx.scene.LightBase; import javafx.scene.Node; import javafx.scene.PerspectiveCamera; import javafx.scene.PointLight; import javafx.scene.Scene; import javafx.scene.image.PixelFormat; import javafx.scene.image.WritableImage; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.input.PickResult; import javafx.scene.paint.Color; import javafx.scene.paint.PhongMaterial; import javafx.scene.shape.Box; import javafx.scene.shape.Cylinder; import javafx.scene.shape.Rectangle; import javafx.scene.shape.Shape3D; import javafx.scene.shape.Sphere; import javafx.scene.transform.Rotate; import javafx.stage.Stage; /* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * * @author fxsqe */ public class BigPointLightWin8TestApp extends Application { public enum TestCaseType { SINGLE_SPHERE_CASE, SINGLE_BOX_CASE, SINGLE_CYLINDER_CASE, } private Scene scene; private static final int WIDTH = 500; private static final int HEIGHT = 500; private Map movers; private List lights; private List nodes; private boolean isThereTestCase; private Group root; private Node currentDragTarget = null; @Override public void start(Stage stage) throws Exception { initScene(); stage.setScene(scene); stage.show(); } protected void initScene() { root = new Group(); isThereTestCase = false; root.setTranslateX(WIDTH / 2); root.setTranslateY(HEIGHT / 2); movers = new HashMap<>(2); lights = new LinkedList<>(); nodes = new LinkedList<>(); scene = new Scene(root, WIDTH, HEIGHT, true); scene.setCamera(new PerspectiveCamera()); scene.setOnMousePressed(new EventHandler() { @Override public void handle(MouseEvent t) { if (t.getButton() == MouseButton.PRIMARY) { PickResult pr = t.getPickResult(); if (pr != null) { Node node = pr.getIntersectedNode(); if (node != null && lights.contains(node.getParent())) { currentDragTarget = node.getParent(); System.out.println(currentDragTarget); return; } if (currentDragTarget != null && node != null && nodes.contains(node)) { ObservableList scope = ((VisibleLight) currentDragTarget).getBase().getScope(); if (scope.contains(node)) { scope.remove(node); } else { scope.add(node); } return; } } currentDragTarget = null; } } }); scene.setOnMouseDragged(new EventHandler() { @Override public void handle(MouseEvent t) { if (t.getButton() == MouseButton.PRIMARY) { if (currentDragTarget != null) { GroupMover mv = movers.get(currentDragTarget); if (mv != null) { mv.translateXProperty().set(t.getSceneX() - WIDTH / 2); mv.translateYProperty().set(t.getSceneY() - HEIGHT / 2); } } } } }); scene.setOnKeyPressed(new EventHandler() { @Override public void handle(KeyEvent t) { switch (t.getText()) { case "1": initTestCase(TestCaseType.SINGLE_SPHERE_CASE); break; case "2": initTestCase(TestCaseType.SINGLE_BOX_CASE); break; case "3": initTestCase(TestCaseType.SINGLE_CYLINDER_CASE); break; case "+": getLightMover(buildNewLight(LightType.Point, Color.RED)).translateXProperty().set(240); break; case "=": getLightMover(buildNewLight(LightType.Ambient, Color.RED)).translateXProperty().set(240); break; } } }); } public GroupMover getLightMover(VisibleLight light) { return movers.get(light); } public VisibleLight[] getVisibleLights() { return lights.toArray(new VisibleLight[0]); } public Node[] getNodes() { return nodes.toArray(new Node[0]); } public VisibleLight buildNewLight(LightType lt, Color color) { VisibleLight newLight = new VisibleLight(color, lt); GroupMover lightMv = new GroupMover(newLight); root.getChildren().add(lightMv.getGroup()); lights.add(newLight); movers.put(newLight, lightMv); return newLight; } public void deleteLight(VisibleLight light) { root.getChildren().remove(movers.get(light).getGroup()); movers.remove(light); lights.remove(light); } public void initTestCase(TestCaseType type) { if (isThereTestCase) { root.getChildren().clear(); nodes.clear(); lights.clear(); movers.clear(); } switch (type) { case SINGLE_SPHERE_CASE: root.getChildren().add(buildSingle(new Sphere(50))); break; case SINGLE_BOX_CASE: root.getChildren().add(buildSingle(new Box(100, 100, 100))); break; case SINGLE_CYLINDER_CASE: root.getChildren().add(buildSingle(new Cylinder(50, 100))); break; } isThereTestCase = true; } private Group buildSingle(Shape3D shape) { Group grp = new Group(shape); nodes.add(shape); return grp; } public static void main(String[] args) { launch(args); } public final class GroupMover { private Group grpX; private Group grpY; private Group grpZ; private Group grp; private void normalizeRotation(DoubleProperty dp) { if (dp.get() > 360) { dp.set(dp.get() - 360); } else if (dp.get() < 0) { dp.set(360 + dp.get()); } } private ChangeListener debugListener = new ChangeListener() { @Override public void changed(ObservableValue ov, Number t, Number t1) { normalizeRotation(rotateXProperty()); normalizeRotation(rotateYProperty()); normalizeRotation(rotateZProperty()); } }; public GroupMover(Node... nodes) { grpX = new Group(nodes); grpX.setRotationAxis(Rotate.X_AXIS); grpY = new Group(grpX); grpY.setRotationAxis(Rotate.Y_AXIS); grpZ = new Group(grpY); grpZ.setRotationAxis(Rotate.Z_AXIS); grp = new Group(grpZ); rotateXProperty().addListener(debugListener); rotateZProperty().addListener(debugListener); rotateYProperty().addListener(debugListener); } public DoubleProperty rotateXProperty() { return grpX.rotateProperty(); } public DoubleProperty rotateYProperty() { return grpY.rotateProperty(); } public DoubleProperty rotateZProperty() { return grpZ.rotateProperty(); } public void setRotateX(double d) { rotateXProperty().set(d); } public void setRotateY(double d) { rotateYProperty().set(d); } public void setRotateZ(double d) { rotateZProperty().set(d); } public Group getGroup() { return grp; } public DoubleProperty translateXProperty() { return grp.translateXProperty(); } public DoubleProperty translateYProperty() { return grp.translateYProperty(); } public DoubleProperty translateZProperty() { return grp.translateZProperty(); } } public enum LightType { Ambient, Point } public class VisibleLight extends Group { private PhongMaterial material; private LightBase lightBase; private LightType type; private void makeConstantImage(WritableImage img, Color color) { int w = (int) img.getWidth(); int h = (int) img.getHeight(); ByteBuffer scanline = ByteBuffer.allocate(3 * w); byte r = (byte) ((int) Math.round(color.getRed() * 255.0)); byte g = (byte) ((int) Math.round(color.getGreen() * 255.0)); byte b = (byte) ((int) Math.round(color.getBlue() * 255.0)); for (int i = 0; i < w; i++) { scanline.put(r); scanline.put(g); scanline.put(b); } scanline.rewind(); img.getPixelWriter().setPixels(0, 0, w, w, PixelFormat.getByteRgbInstance(), scanline, 0); } public VisibleLight(Color color) { this(color, LightType.Point); } public VisibleLight(Color color, LightType lt) { type = lt; if (lt.equals(LightType.Point)) { lightBase = new PointLight(); } else { lightBase = new AmbientLight(); } material = new PhongMaterial(); material.setDiffuseMap(null); material.setBumpMap(null); material.setSpecularMap(null); material.setSpecularColor(Color.TRANSPARENT); setColor(color); final Sphere light = new Sphere(50); light.setScaleX(0.2); light.setScaleY(0.2); light.setScaleZ(0.2); light.setMaterial(material); this.getChildren().addAll(lightBase, light); } public AmbientLight getAmbient() { if (type == LightType.Point) { return null; } return (AmbientLight) lightBase; } public PointLight getPoint() { if (type == LightType.Ambient) { return null; } return (PointLight) lightBase; } public LightBase getBase() { return lightBase; } public void setLightType(LightType lt) { this.getChildren().remove(lightBase); if (lt.equals(LightType.Point)) { lightBase = new PointLight(lightBase.getColor()); } else { lightBase = new AmbientLight(lightBase.getColor()); } this.getChildren().add(lightBase); } public final void setColor(Color color) { lightBase.setColor(color); WritableImage selfIllumMap = new WritableImage(64, 64); makeConstantImage(selfIllumMap, color); material.setSelfIlluminationMap(selfIllumMap); } } }