Problem
I'd like to apply a diffuse map to a MeshView. When I apply a Material with the diffuse map to the MeshView, it's not visible. The same material applied to a Box however is visible.
Question
What do I have to do to apply a diffuse map to a MeshView?
Code
The code generates an Image with random noise. The image is used as diffuse map in a PhongMaterial. The image is displayed, above it the box with the material applied, and above the box the MeshView (a pyramid) with the material applied. The material isn't visible on the pyramid. You can use mouse dragging for rotation.
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
public class Test extends Application {
private double mousePosX, mousePosY;
private double mouseOldX, mouseOldY;
private final Rotate rotateX = new Rotate(20, Rotate.X_AXIS);
private final Rotate rotateY = new Rotate(-45, Rotate.Y_AXIS);
@Override
public void start(Stage primaryStage) {
// cube
Group group = new Group();
// size of the cube
double size = 400;
group.getTransforms().addAll(rotateX, rotateY);
Image diffuseMap = createImage( size);
// show noise image
ImageView iv = new ImageView( diffuseMap);
iv.setTranslateX(-0.5*size);
iv.setTranslateY(-0.20*size);
iv.setRotate(90);
iv.setRotationAxis(new Point3D(1,0,0));
group.getChildren().add( iv);
// create material out of the noise image
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(diffuseMap);
// create box with noise diffuse map
Box box = new Box( 100,100,100);
box.setMaterial(material);
group.getChildren().add( box);
// create pyramid with diffuse map
float h = 150; // Height
float s = 150; // Side
TriangleMesh pyramidMesh = new TriangleMesh();
pyramidMesh.getTexCoords().addAll(1,1,1,0,0,1,0,0);
pyramidMesh.getPoints().addAll(
0, 0, 0, // Point 0 - Top
0, h, -s/2, // Point 1 - Front
-s/2, h, 0, // Point 2 - Left
s/2, h, 0, // Point 3 - Back
0, h, s/2 // Point 4 - Right
);
pyramidMesh.getFaces().addAll(
0,0, 2,0, 1,0, // Front left face
0,0, 1,0, 3,0, // Front right face
0,0, 3,0, 4,0, // Back right face
0,0, 4,0, 2,0, // Back left face
4,0, 1,0, 2,0, // Bottom rear face
4,0, 3,0, 1,0 // Bottom front face
);
MeshView pyramid = new MeshView(pyramidMesh);
pyramid.setDrawMode(DrawMode.FILL);
pyramid.setTranslateY(-250);
// apply material
// TODO: why is the diffuse map not displayed?
pyramid.setMaterial(material);
group.getChildren().add(pyramid);
// scene
StackPane root = new StackPane();
root.getChildren().add(group);
Scene scene = new Scene(root, 1600, 900, true, SceneAntialiasing.BALANCED);
scene.setCamera(new PerspectiveCamera());
// interaction listeners
scene.setOnMousePressed(me -> {
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
});
scene.setOnMouseDragged(me -> {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
rotateX.setAngle(rotateX.getAngle()-(mousePosY - mouseOldY));
rotateY.setAngle(rotateY.getAngle()+(mousePosX - mouseOldX));
mouseOldX = mousePosX;
mouseOldY = mousePosY;
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Create image with random noise
*/
public Image createImage( double size) {
Random rnd = new Random();
int width = (int) size;
int height = (int) size;
WritableImage wr = new WritableImage(width, height);
PixelWriter pw = wr.getPixelWriter();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
Color color = Color.rgb(rnd.nextInt( 256), rnd.nextInt( 256), rnd.nextInt( 256));
pw.setColor(x, y, color);
}
}
return wr;
}
public static void main(String[] args) {
launch(args);
}
}
Screenshot
Thank you very much for the help!