/** * SphereSegments.java * * Copyright (c) 2013-2016, F(X)yz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of F(X)yz, any associated website, nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.fxyz3d.pending; import java.util.Random; import javafx.scene.AmbientLight; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.PerspectiveCamera; import javafx.scene.PointLight; import javafx.scene.SceneAntialiasing; import javafx.scene.SubScene; import javafx.scene.input.KeyCode; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Background; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.transform.Rotate; import javafx.scene.transform.Translate; import javafx.stage.Stage; import org.fxyz3d.samples.FXyzSample; import org.fxyz3d.shapes.SphereSegment; import org.fxyz3d.utils.CameraTransformer; /** * * @author Sean */ public class SphereSegments extends FXyzSample { @Override public Node getSample() { PerspectiveCamera camera = new PerspectiveCamera(true); final double sceneWidth = 800; final double sceneHeight = 600; final CameraTransformer cameraTransform = new CameraTransformer(); Group sceneRoot = new Group(); SubScene scene = new SubScene(sceneRoot, sceneWidth, sceneHeight, true, SceneAntialiasing.BALANCED); scene.setFill(Color.BLACK); //setup camera transform for rotational support cameraTransform.setTranslate(0, 0, 0); cameraTransform.getChildren().add(camera); camera.setNearClip(0.1); camera.setFarClip(10000.0); camera.setTranslateZ(-2000); cameraTransform.ry.setAngle(-45.0); cameraTransform.rx.setAngle(-10.0); //add a Point Light for better viewing of the grid coordinate system PointLight light = new PointLight(Color.WHITE); cameraTransform.getChildren().add(light); cameraTransform.getChildren().add(new AmbientLight(Color.WHITE)); light.setTranslateX(camera.getTranslateX()); light.setTranslateY(camera.getTranslateY()); light.setTranslateZ(camera.getTranslateZ()); scene.setCamera(camera); //Make a bunch of semi random sphere segments and stuff Group sphereGroup = new Group(); for (int i = 0; i < 30; i++) { Random r = new Random(); //A lot of magic numbers in here that just artificially constrain the math float randomRadius = (float) ((r.nextFloat() * 150) + 10); float randomThetaMax = (float) ((r.nextFloat() * 360) + 1); float randomThetaMin = (float) ((r.nextFloat()) + 1); if (randomThetaMin > randomThetaMax) { float swap = randomThetaMin; randomThetaMin = randomThetaMax; randomThetaMax = swap; } float randomPolarMax = (float) ((r.nextFloat() * 90) + 1); float randomPolarMin = (float) ((r.nextFloat()) + 1); if (randomPolarMin > randomPolarMax) { float swap = randomPolarMin; randomPolarMin = randomPolarMax; randomPolarMax = swap; } int randomSegments = (int) ((r.nextFloat() * 15) + 5); Color randomColor = new Color(r.nextDouble(), r.nextDouble(), r.nextDouble(), r.nextDouble()); boolean ambientRandom = r.nextBoolean(); boolean fillRandom = r.nextBoolean(); SphereSegment sphereSegment = new SphereSegment(randomRadius, randomColor, Math.toRadians(0), Math.toRadians(360), Math.toRadians(randomPolarMin), Math.toRadians(randomPolarMax), randomSegments, ambientRandom, fillRandom); double translationX = Math.random() * sceneWidth / 2; if (Math.random() >= 0.5) { translationX *= -1; } double translationY = Math.random() * sceneWidth / 2; if (Math.random() >= 0.5) { translationY *= -1; } double translationZ = Math.random() * sceneWidth / 2; if (Math.random() >= 0.5) { translationZ *= -1; } Translate translate = new Translate(translationX, translationY, translationZ); Rotate rotateX = new Rotate(Math.random() * 360, Rotate.X_AXIS); Rotate rotateY = new Rotate(Math.random() * 360, Rotate.Y_AXIS); Rotate rotateZ = new Rotate(Math.random() * 360, Rotate.Z_AXIS); sphereSegment.getTransforms().addAll(translate, rotateX, rotateY, rotateZ); sphereSegment.getTransforms().add(translate); sphereGroup.getChildren().add(sphereSegment); } sceneRoot.getChildren().addAll(sphereGroup); //First person shooter keyboard movement scene.setOnKeyPressed(event -> { double change = 10.0; //Add shift modifier to simulate "Running Speed" if (event.isShiftDown()) { change = 50.0; } //What key did the user press? KeyCode keycode = event.getCode(); //Step 2c: Add Zoom controls if (keycode == KeyCode.W) { camera.setTranslateZ(camera.getTranslateZ() + change); } if (keycode == KeyCode.S) { camera.setTranslateZ(camera.getTranslateZ() - change); } //Step 2d: Add Strafe controls if (keycode == KeyCode.A) { camera.setTranslateX(camera.getTranslateX() - change); } if (keycode == KeyCode.D) { camera.setTranslateX(camera.getTranslateX() + change); } }); scene.setOnMousePressed((MouseEvent me) -> { mousePosX = me.getSceneX(); mousePosY = me.getSceneY(); mouseOldX = me.getSceneX(); mouseOldY = me.getSceneY(); }); scene.setOnMouseDragged((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 = 0.1; } if (me.isShiftDown()) { modifier = 50.0; } if (me.isPrimaryButtonDown()) { cameraTransform.ry.setAngle(((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180); // + cameraTransform.rx.setAngle(((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180); // - } else if (me.isSecondaryButtonDown()) { double z = camera.getTranslateZ(); double newZ = z + mouseDeltaX * modifierFactor * modifier; camera.setTranslateZ(newZ); } 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); // - } }); StackPane sp = new StackPane(); sp.setPrefSize(sceneWidth, sceneHeight); sp.setMaxSize(StackPane.USE_COMPUTED_SIZE, StackPane.USE_COMPUTED_SIZE); sp.setMinSize(StackPane.USE_COMPUTED_SIZE, StackPane.USE_COMPUTED_SIZE); sp.setBackground(Background.EMPTY); sp.getChildren().add(scene); sp.setPickOnBounds(false); scene.widthProperty().bind(sp.widthProperty()); scene.heightProperty().bind(sp.heightProperty()); return (sp); } @Override public Node getPanel(Stage stage) { return getSample(); } @Override public String getJavaDocURL() { return null; } @Override protected Node buildControlPanel() { return null; } }