如何为 fxyz3d 形状指定材质?当我添加到 3D 对象的 JavaFX 组时,fxyz3d 节点
Cone cone = new Cone(coneFacets, coneRadius, coneHeight);
cone.setMaterial(Materials.redMaterial());
无论指定的材料是什么,它都会将该组中的每个形状变成纯黑色,而不仅仅是圆锥体。如果我注释掉上面的两行和将圆锥添加到组中的那一行,其他形状的所有显示都会返回到它们指定的外观。
我正在使用 javafx-sdk-17.0.1、fxyz3d-0.5.4.jar、JavaSE-16、Windows 10。Javadoc 在任何地方都可用于 fxyz3d 吗?还是需要下载源码并在本地构建?
redMaterial 定义为
final PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.INDIANRED);
material.setSpecularColor(Color.RED);
以下代码将重现这一点。照原样,圆锥体和圆柱体都显示为黑色。注释掉创建和添加锥体的四行,圆柱体将显示为材料指定的红色。(不要将此作为起点示例,因为在用户调整舞台窗口大小时自动缩放也存在问题尚未解决。)
package org.javafxtests;
import org.fxyz3d.shapes.Cone;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Label;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Cylinder;
import javafx.stage.Stage;
public class JxyzConeMaterials extends Application {
// https://www.tutorialspoint.com/javafx/index.htm
// https://www.javatpoint.com/javafx-tutorial
// https://openjfx.io/javadoc/11/
/**
* The application initialization method.
*/
@Override
public void init() throws Exception {
super.init();
}
/**
* Main entry point for all JavaFX applications. The start method is called
* after the init method has returned and the JavaFX framework and hosting
* system are ready to start the application.
*/
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test JXzy Cone materials");
double sceneWidth = 750.0d;
double sceneHeight = 500.0d;
// The scene structure is constructed from the inside-out (bottom-up).
// A tool bar goes along the top
final FlowPane toolbar = new FlowPane();
toolbar.setPrefWidth(Double.MAX_VALUE);
toolbar.getChildren().addAll(new Label("Files"));
// A TreeView goes down the left side
final TreeView<String> treeView = new TreeView<String>();
treeView.setPrefHeight(Double.MAX_VALUE);
TreeItem<String> treeRoot = new TreeItem<String>("<empty>");
treeView.setRoot(treeRoot);
// A SubScene for viewing 3D objects goes to the right of the TreeView
final SubScene canvasScene = new SubScene(new AnchorPane(), 0, 0);
final AnchorPane canvasRootPane = (AnchorPane) canvasScene.getRoot();
canvasRootPane.setPrefWidth(Double.MAX_VALUE);
canvasRootPane.setPrefHeight(Double.MAX_VALUE);
canvasScene.setWidth(0.75 * sceneWidth); // No setPref methods
canvasScene.setHeight(sceneHeight);
// Create a controllable camera for the 3D SubScene
final PerspectiveCamera canvasCamera = new PerspectiveCamera(true);
final Group cameraTruck = new Group();
final Group cameraGimbal = new Group();
canvasCamera.setFarClip(6000);
canvasCamera.setNearClip(0.01);
cameraGimbal.getChildren().add(canvasCamera);
cameraTruck.getChildren().add(cameraGimbal);
cameraTruck.setTranslateZ(-500.0d);
canvasScene.setCamera(canvasCamera);
canvasRootPane.getChildren().add(cameraTruck);
// Create an HBox at the bottom of the scene,
// TreeView on the left and 3D canvas on the right.
HBox treeAnd3dViews = new HBox(treeView, canvasScene);
treeAnd3dViews.setFillHeight(true);
HBox.setHgrow(canvasScene, Priority.ALWAYS);
treeAnd3dViews.setMaxHeight(Double.MAX_VALUE);
treeAnd3dViews.setMaxWidth(Double.MAX_VALUE);
// Create a VBox to stack the tool bar over the above.
VBox toolbarOverViews = new VBox(toolbar, treeAnd3dViews);
toolbarOverViews.setMaxWidth(Double.MAX_VALUE);
toolbarOverViews.setMaxHeight(Double.MAX_VALUE);
VBox.setVgrow(treeAnd3dViews, Priority.ALWAYS);
AnchorPane.setTopAnchor(toolbarOverViews, 0.0);
AnchorPane.setBottomAnchor(toolbarOverViews, 0.0);
AnchorPane.setLeftAnchor(toolbarOverViews, 0.0);
AnchorPane.setRightAnchor(toolbarOverViews, 0.0);
final Scene scene = new Scene(new AnchorPane(), sceneWidth, sceneHeight);
final AnchorPane sceneRootPane = (AnchorPane) scene.getRoot();
sceneRootPane.getChildren().add(toolbarOverViews);
// Draw an arrow consisting of a cylinder with a cone on top.
double lineRadius = 1.0d;
double lineLength = 25.0d;
int coneFacets = 6;
double coneRadius = 3.0d;
double coneHeight = 6.0d;
final PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.INDIANRED);
material.setSpecularColor(Color.RED);
Cylinder cylinder = new Cylinder(lineRadius, lineLength);
cylinder.setMaterial(material);
Cone cone = new Cone(coneFacets, coneRadius, coneHeight);
cone.setMaterial(material);
// The cone points in the negative Y direction
cone.setTranslateY(-(lineLength / 2.0d) - coneHeight );
canvasRootPane.getChildren().add(cylinder);
canvasRootPane.getChildren().add(cone);
// Show
primaryStage.setScene(scene);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
}
/**
* Main method to launch the application with parameters if needed.
* This may or may not be called, depending on how this application
* is launched.
*
* @param args specifies arguments to {@linkplain Application#launch)}.
*/
public static void main(String[] args) {
launch(args);
}
}