javaFX初探(选择)
本章主要介绍,javaFX 3D库中的PickResult API。PickResult API 早就在2D的视角相机中就可用了,然而,当用到深度缓存的时候依旧有点限制,PickResult类在javafx。scene。input包下,它是选择事件的容器。创建PickResult对象// Creates a pick result for a 2D case where no ad
·
本章主要介绍,javaFX 3D库中的PickResult API。
PickResult API 早就在2D的视角相机中就可用了,然而,当用到深度缓存的时候依旧有点限制,PickResult类在javafx。scene。input包
下,它是选择事件的容器。
创建PickResult对象
// Creates a pick result for a 2D case where no additional information
// is needed. Converts the given scene coordinates to the target's local
// coordinate space andstores the value as the intersected point. Sets
// intersected node to the giventarget, distance to 1.0, face to
// FACE_UNDEFINED and texCoord to null
PickResult(EventTarget target, double sceneX, double sceneY)
// Creates a new instance of PickResult for a non-3d-shape target. Sets face
// to FACE_UNDEFINED and texCoord to null.
PickResult(Node node, Point3D point, double distance)
// Creates a new instance of PickResult
PickResult(Node node, Point3D point, double distance, int face,
Point2D texCoord)
PickResult对象的方法
// Returns the intersected node. Returns null if there was no intersection
// with any node and the scene was picked.
public final Node getIntersectedNode()
// Returns the intersected point in local coordinate of the picked Node. If
// no node was picked, it returns the intersected point with the ion
// plane.
public final Point3D getIntersectedPoint()
// Returns the intersected distance between camera position and the
// intersected point
public final double getIntersectedDistance()
// Returns the intersected face of the picked Node, FACE_UNDEFINED if the
// node doesn't have user-specified faces or was picked on bounds.
public final int getIntersectedFace()
// Return the intersected texture coordinates of the picked 3d shape. If the
// picked target is not Shape3D or has pickOnBounds==true, it returns null.
// Returns new Point2D presenting the intersected TexCoord
public final Point2D getIntersectedTexCoord()
PcikResult的实例
下面的例子展示了PickResult对象和方法得使用。这个实例展示了怎么从PickResult对象中获取信息,当你的鼠标在网格上移动的时候,
鼠标的位置就会显示在上边,
/*
* Copyright (c) 2014, Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* 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 Oracle 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 THE COPYRIGHT
* OWNER OR CONTRIBUTORS 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 com.chu.helloworld;
import javafx.application.Application;
import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Point3D;
import javafx.geometry.VPos;
import javafx.scene.Camera;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.PickResult;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape3D;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
/**
* A Simple Picking Example
*/
public class PickMesh3D extends Application {
MeshView meshView;
final static float minX = -10;
final static float minY = -10;
final static float maxX = 10;
final static float maxY = 10;
static TriangleMesh buildTriangleMesh(int subDivX, int subDivY, float scale) {
final int pointSize = 3;
final int texCoordSize = 2;
// 3 point indices and 3 texCoord indices per triangle
final int faceSize = 6;
int numDivX = subDivX + 1;
int numVerts = (subDivY + 1) * numDivX;
float points[] = new float[numVerts * pointSize];
float texCoords[] = new float[numVerts * texCoordSize];
int faceCount = subDivX * subDivY * 2;
int faces[] = new int[faceCount * faceSize];
// Create points and texCoords
for (int y = 0; y <= subDivY; y++) {
float dy = (float) y / subDivY;
double fy = (1 - dy) * minY + dy * maxY;
for (int x = 0; x <= subDivX; x++) {
float dx = (float) x / subDivX;
double fx = (1 - dx) * minX + dx * maxX;
int index = y * numDivX * pointSize + (x * pointSize);
points[index] = (float) fx * scale;
points[index + 1] = (float) fy * scale;
points[index + 2] = 0.0f;
index = y * numDivX * texCoordSize + (x * texCoordSize);
texCoords[index] = dx;
texCoords[index + 1] = dy;
}
}
// Create faces
for (int y = 0; y < subDivY; y++) {
for (int x = 0; x < subDivX; x++) {
int p00 = y * numDivX + x;
int p01 = p00 + 1;
int p10 = p00 + numDivX;
int p11 = p10 + 1;
int tc00 = y * numDivX + x;
int tc01 = tc00 + 1;
int tc10 = tc00 + numDivX;
int tc11 = tc10 + 1;
int index = (y * subDivX * faceSize + (x * faceSize)) * 2;
faces[index + 0] = p00;
faces[index + 1] = tc00;
faces[index + 2] = p10;
faces[index + 3] = tc10;
faces[index + 4] = p11;
faces[index + 5] = tc11;
index += faceSize;
faces[index + 0] = p11;
faces[index + 1] = tc11;
faces[index + 2] = p01;
faces[index + 3] = tc01;
faces[index + 4] = p00;
faces[index + 5] = tc00;
}
}
TriangleMesh triangleMesh = new TriangleMesh();
triangleMesh.getPoints().setAll(points);
triangleMesh.getTexCoords().setAll(texCoords);
triangleMesh.getFaces().setAll(faces);
return triangleMesh;
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
throw new RuntimeException("*** ERROR: common conditional SCENE3D is not supported");
}
stage.setTitle("JavaFX 3D Simple Picking demo");
final PerspectiveCamera camera = new PerspectiveCamera();
Node pickResultPanel = createOverlay();
Group root = new Group();
root.getChildren().addAll(pickResultPanel, createSubScene(camera));
Scene scene = new Scene(root, 800, 800);
scene.setFill(Color.color(0.2, 0.2, 0.2));
scene.setOnKeyTyped(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent e) {
switch (e.getCharacter()) {
case "L":
System.err.print("L ");
boolean wireframe = meshView.getDrawMode() == DrawMode.LINE;
meshView.setDrawMode(wireframe ? DrawMode.FILL : DrawMode.LINE);
break;
}
}
});
stage.setScene(scene);
stage.show();
stage.requestFocus();
}
private Node createSimpleMesh() {
TriangleMesh triangleMesh = buildTriangleMesh(2, 2, 30);
meshView = new MeshView(triangleMesh);
activateShape(meshView, "Simple Mesh");
meshView.setDrawMode(DrawMode.FILL);
meshView.setCullFace(CullFace.NONE);
PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.GOLD);
material.setSpecularColor(Color.rgb(30, 30, 30));
meshView.setMaterial(material);
Node group = new Group(meshView);
group.setTranslateX(550);
group.setTranslateY(550);
return group;
}
private void activateShape(final Shape3D shape, final String name) {
shape.setId(name);
EventHandler<MouseEvent> moveHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
PickResult res = event.getPickResult();
setState(res);
event.consume();
}
};
shape.setOnMouseMoved(moveHandler);
shape.setOnMouseDragOver(moveHandler);
shape.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
PickResult res = event.getPickResult();
if (res == null) {
System.err.println("Mouse entered has not pickResult");
}
setState(res);
}
});
shape.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
PickResult res = event.getPickResult();
if (res == null) {
System.err.println("Mouse exited has not pickResult");
}
setState(res);
event.consume();
}
});
}
Text caption, data;
private Node createOverlay() {
HBox hBox = new HBox(10);
caption = new Text("Node:\n\nPoint:\nTexture Coord:\nFace:\nDistance:");
caption.setFont(Font.font("Times New Roman", 18));
caption.setTextOrigin(VPos.TOP);
caption.setTextAlignment(TextAlignment.RIGHT);
data = new Text("-- None --\n\n\n\n");
data.setFont(Font.font("Times New Roman", 18));
data.setTextOrigin(VPos.TOP);
data.setTextAlignment(TextAlignment.LEFT);
Rectangle rect = new Rectangle(300, 150, Color.color(0.2, 0.5, 0.3, 0.8));
hBox.getChildren().addAll(caption, data);
return new Group(rect, hBox);
}
private SubScene createSubScene(Camera camera) {
final Node simpleMesh = createSimpleMesh();
final Group parent = new Group(simpleMesh);
parent.setTranslateZ(600);
parent.setTranslateX(-150);
parent.setTranslateY(-200);
parent.setScaleX(0.8);
parent.setScaleY(0.8);
parent.setScaleZ(0.8);
final PointLight pointLight = new PointLight(Color.ANTIQUEWHITE);
pointLight.setTranslateX(100);
pointLight.setTranslateY(100);
pointLight.setTranslateZ(-300);
final Group root = new Group(parent, pointLight, new Group(camera));
root.setDepthTest(DepthTest.ENABLE);
final SubScene subScene = new SubScene(root, 800, 800, true, SceneAntialiasing.BALANCED);
subScene.setCamera(camera);
subScene.setFill(Color.TRANSPARENT);
subScene.setId("SubScene");
return subScene;
}
<strong> final void setState(PickResult result) {
if (result.getIntersectedNode() == null) {
data.setText("Scene\n\n"
+ point3DToString(result.getIntersectedPoint()) + "\n"
+ point2DToString(result.getIntersectedTexCoord()) + "\n"
+ result.getIntersectedFace() + "\n"
+ String.format("%.1f", result.getIntersectedDistance()));
} else {
data.setText(result.getIntersectedNode().getId() + "\n"
+ getCullFace(result.getIntersectedNode()) + "\n"
+ point3DToString(result.getIntersectedPoint()) + "\n"
+ point2DToString(result.getIntersectedTexCoord()) + "\n"
+ result.getIntersectedFace() + "\n"
+ String.format("%.1f", result.getIntersectedDistance()));
}
}</strong>
private static String point3DToString(Point3D pt) {
if (pt == null) {
return "null";
}
return String.format("%.1f; %.1f; %.1f", pt.getX(), pt.getY(), pt.getZ());
}
private static String point2DToString(Point2D pt) {
if (pt == null) {
return "null";
}
return String.format("%.2f; %.2f", pt.getX(), pt.getY());
}
private static String getCullFace(Node n) {
if (n instanceof Shape3D) {
return "(CullFace." + ((Shape3D) n).getCullFace() + ")";
}
return "";
}
}
运行显示如下:
更多推荐
已为社区贡献2条内容
所有评论(0)