1

How do I specify a material for an fxyz3d shape? When I add to a JavaFX Group of 3D objects the fxyz3d node

    Cone cone = new Cone(coneFacets, coneRadius, coneHeight);
    cone.setMaterial(Materials.redMaterial());

it turns every shape in that group solid black, not just the cone, regardless of what any of the specified materials are. If I comment out the above two lines and the one that adds the cone to the group, all the displays of the other shapes return to their specified appearances.

I am using javafx-sdk-17.0.1, fxyz3d-0.5.4.jar, JavaSE-16, Windows 10. Is Javadoc available for fxyz3d anywhere? Or is it necessary to download source and build it locally?

The redMaterial is defined as

   final PhongMaterial material = new PhongMaterial();
   material.setDiffuseColor(Color.INDIANRED);
   material.setSpecularColor(Color.RED);

The following code will reproduce this. As is, both cone and cylinder display black. Comment out the four lines that create and add the Cone, and the cylinder will display red as specified by the material. (Don't otherwise use this as a starting-point example, as there are also issues with automatic scaling as the user adjusts the stage window size yet to be addressed.)

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);
    }
    
}
SteveVZZZ
  • 71
  • 4
  • `fxyz3d-0.5.4` source and javadoc artifacts are [here](https://repo1.maven.org/maven2/org/fxyz3d/fxyz3d/0.5.4/); please [edit] your question to include a [mre] that shows your current approach. – trashgod Dec 28 '21 at 18:34
  • Maybe you should be using JDK 17.0.1 with openjfx 17.0.1 ? – Abra Dec 30 '21 at 06:00
  • I tried jdk 17.0.1. The Jxyz3d web site cited JavaFX 11, so I tried that also. Same results. – SteveVZZZ Dec 30 '21 at 21:02
  • It gets even stranger. The following uses only jdk 17.0.1 and javafx-sdk-17.0.1. Switching between Color.BLUE and a more detailed material specification causes the node to vanish into thin air... – SteveVZZZ Dec 30 '21 at 21:52
  • Somehow the `Cone` shape is not rendering correctly (it is always black). You can use [`ConeMesh`](https://github.com/FXyz/FXyz/blob/master/FXyz-Core/src/main/java/org/fxyz3d/shapes/primitives/ConeMesh.java) instead. – José Pereda Dec 31 '21 at 10:08
  • ConeMesh does it, thanks! – SteveVZZZ Jan 01 '22 at 20:29

0 Answers0