-
-
Save Birdasaur/bf8ad77d052f42aaf943933fdaf1496e to your computer and use it in GitHub Desktop.
package edu.jhuapl.trinity.javafx; | |
import java.util.ArrayList; | |
import java.util.List; | |
import javafx.application.Application; | |
import javafx.geometry.Insets; | |
import javafx.geometry.Point3D; | |
import javafx.scene.Group; | |
import javafx.scene.PerspectiveCamera; | |
import javafx.scene.Scene; | |
import javafx.scene.SceneAntialiasing; | |
import javafx.scene.SpotLight; | |
import javafx.scene.SubScene; | |
import javafx.scene.input.MouseEvent; | |
import javafx.scene.input.ScrollEvent; | |
import javafx.scene.layout.Background; | |
import javafx.scene.layout.BackgroundFill; | |
import javafx.scene.layout.BorderPane; | |
import javafx.scene.layout.CornerRadii; | |
import javafx.scene.layout.StackPane; | |
import javafx.scene.paint.Color; | |
import javafx.scene.paint.PhongMaterial; | |
import javafx.scene.shape.Box; | |
import javafx.scene.shape.CullFace; | |
import javafx.scene.shape.DrawMode; | |
import javafx.stage.Stage; | |
import org.fxyz3d.geometry.MathUtils; | |
import org.fxyz3d.utils.CameraTransformer; | |
public class SpotLightTest extends Application { | |
protected Box box; | |
PerspectiveCamera camera = new PerspectiveCamera(true); | |
public Group sceneRoot = new Group(); | |
public SubScene subScene; | |
public CameraTransformer cameraTransform = new CameraTransformer(); | |
private double cameraDistance = -4000; | |
private final double sceneWidth = 10000; | |
private final double sceneHeight = 4000; | |
private double mousePosX; | |
private double mousePosY; | |
private double mouseOldX; | |
private double mouseOldY; | |
private double mouseDeltaX; | |
private double mouseDeltaY; | |
@Override | |
public void start(Stage primaryStage) throws Exception { | |
subScene = new SubScene(sceneRoot, sceneWidth, sceneHeight, true, SceneAntialiasing.BALANCED); | |
//Start Tracking mouse movements only when a button is pressed | |
subScene.setOnMouseDragged((MouseEvent me) -> mouseDragCamera(me)); | |
subScene.setOnScroll((ScrollEvent event) -> { | |
double modifier = 50.0; | |
double modifierFactor = 0.1; | |
if (event.isControlDown()) { | |
modifier = 1; | |
} | |
if (event.isShiftDown()) { | |
modifier = 100.0; | |
} | |
double z = camera.getTranslateZ(); | |
double newZ = z + event.getDeltaY() * modifierFactor * modifier; | |
camera.setTranslateZ(newZ); | |
}); | |
StackPane stackPane = new StackPane(subScene); | |
subScene.widthProperty().bind(stackPane.widthProperty()); | |
subScene.heightProperty().bind(stackPane.heightProperty()); | |
subScene.setFill(Color.LIGHTGREY); | |
camera = new PerspectiveCamera(true); | |
//setup camera transform for rotational support | |
cameraTransform.setTranslate(0, 0, 0); | |
cameraTransform.getChildren().add(camera); | |
camera.setNearClip(0.1); | |
camera.setFarClip(100000.0); | |
camera.setTranslateZ(cameraDistance); | |
cameraTransform.ry.setAngle(-45.0); | |
cameraTransform.rx.setAngle(-10.0); | |
subScene.setCamera(camera); | |
//create multiple spot lights | |
List<SpotLight> lights = new ArrayList<>(); | |
lights.add(new SpotLight(Color.WHITE)); | |
lights.add(new SpotLight(Color.GREEN)); | |
lights.add(new SpotLight(Color.RED)); | |
for(int i=0; i< lights.size(); i++) { | |
SpotLight spotLight = lights.get(i); | |
spotLight.setDirection(new Point3D(0, 1, 0)); | |
spotLight.setInnerAngle(120); | |
spotLight.setOuterAngle(30); | |
spotLight.setFalloff(-0.4); | |
spotLight.setTranslateZ(2000 * i); | |
spotLight.setTranslateY(-200); | |
} | |
box = new Box(sceneWidth, 50, sceneWidth); | |
box.setDrawMode(DrawMode.FILL); | |
box.setCullFace(CullFace.BACK); | |
box.setMaterial(new PhongMaterial(Color.CYAN)); | |
sceneRoot.getChildren().addAll(cameraTransform, box); | |
sceneRoot.getChildren().addAll(lights); | |
BorderPane bpOilSpill = new BorderPane(subScene); | |
stackPane.getChildren().clear(); | |
stackPane.getChildren().addAll(bpOilSpill); | |
stackPane.setPadding(new Insets(10)); | |
stackPane.setBackground(new Background(new BackgroundFill(Color.rgb(255, 255, 255), CornerRadii.EMPTY, Insets.EMPTY))); | |
Scene scene = new Scene(stackPane, 1000, 1000); | |
scene.setOnMouseEntered(event -> subScene.requestFocus()); | |
primaryStage.setTitle("Multiple SpotLight Test"); | |
primaryStage.setScene(scene); | |
primaryStage.show(); | |
} | |
private void mouseDragCamera(MouseEvent me) { | |
mouseOldX = mousePosX; | |
mouseOldY = mousePosY; | |
mousePosX = me.getSceneX(); | |
mousePosY = me.getSceneY(); | |
mouseDeltaX = (mousePosX - mouseOldX); | |
mouseDeltaY = (mousePosY - mouseOldY); | |
double modifier = 10.0; | |
double modifierFactor = 0.1; | |
if (me.isControlDown()) { | |
modifier = 1; | |
} | |
if (me.isShiftDown()) { | |
modifier = 50.0; | |
} | |
if (me.isPrimaryButtonDown()) { | |
if(me.isAltDown()) { //roll | |
cameraTransform.rz.setAngle(((cameraTransform.rz.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180); // + | |
} else { | |
cameraTransform.ry.setAngle(((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180); // + | |
cameraTransform.rx.setAngle( | |
MathUtils.clamp(-60, | |
(((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180), | |
60)); // - | |
} | |
} else if (me.isMiddleButtonDown() ) { | |
cameraTransform.t.setX(cameraTransform.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3); // - | |
cameraTransform.t.setY(cameraTransform.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3); // - | |
} | |
} | |
public static void main(String[] args){launch(args);} | |
} |
The amount of light is per pixel, not per node. There is no way to determine it per pixel programatically, otherwise no one would need shaders. At best you can take a snapshot and sample that specific pixel for its RGB. Remember that it depends also on the location of the camera because of the way the light reflects. If you want some sort of approximation per node then use the formula in PhongMaterial
.
If you want some sort of approximation per node then use the formula in
PhongMaterial
.
Oh good idea. An approximation would be fine. I suddenly have an idea for a game mechanic where you must use spot lights to shine light on "adversaries" or other targets. Each target would require different amounts of light/color to be "defeated".
By using the lighting I can play games with visibility... certain nodes would be difficult to see in bright lights so you may have to invert the light to be a shadow cast.
I can see a flat plane with 3D shapes moving around on the plane either towards you or towards a goal and you are using light/shadow to manipulate the playing field.
oooo different colors could put spin and velocity effects on the 3D shapes. Oh this could be really cool.
Gotcha. So practically speaking its a sort of AND operation. This makes sense. Thanks!
Last question... is there some way/method for knowing how much total light contribution is being applied to a given node programmatically?
I can think of some cool game ideas if you could programmatically determine the amount of light contribution (even better if its known by RGB channel) on a node.