gpt4 book ai didi

javafx - 在JavaFX中,如何为网格的反面着色?

转载 作者:行者123 更新时间:2023-12-02 19:45:54 26 4
gpt4 key购买 nike

我正在 JavaFX 中使用 this answer 中讨论的相同技术创建 3D 绘图。 ,用 MeshView 和 PhongMaterial 提供颜色。但是,只有 Material 的顶部是彩色的,如果用户旋转相机从下方查看,则无法确定绘图的形状,因为它是全黑的。

我的问题:

  1. 有没有办法设置网格反面的 Material ?
  2. 如果没有,是否有一个好的方法来“伪造”它?我想在完全相同的位置创建一个颠倒的新网格会导致渲染问题;最好的方法是应用一个非常小的偏移量,以便两个网格不完全重叠?

编辑:我在下面包含了一些示例代码,这些代码是从我的真实代码中删除的,但包含足够的内容来说明问题。默认情况下,它显示网格的顶部,在本例中为红色。如果更改 new Rotate(-30, Rotate.X_AXIS) 行,使角度变为 +30 而不是 -30,它将旋转相机以显示网格的底面,您将看到它显示为黑色。

package test;

import javafx.application.Application;
import javafx.scene.DepthTest;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.image.Image;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
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.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class TestApp extends Application {

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage stage) throws Exception {
TestPlot tp = new TestPlot();
tp.setPrefSize(600, 400);
Scene scene = new Scene(tp);
stage.setScene(scene);
stage.show();
}

class TestPlot extends Region {
private final PerspectiveCamera camera = new PerspectiveCamera(true);
private double[][] data = new double[500][500];
private final StackPane root = new StackPane();
private final SubScene subscene;

public TestPlot() {
subscene = new SubScene(root, 1, 1, true, SceneAntialiasing.BALANCED);
subscene.setCamera(camera);
getChildren().add(subscene);

widthProperty().addListener((obs, oldVal, newVal) -> refreshPlot());
heightProperty().addListener((obs, oldVal, newVal) -> refreshPlot());
refreshPlot();
}

private void refreshPlot() {
// Set the subscene bounds to match the plot bounds, in case the plot was
// resized
subscene.setHeight(this.getHeight());
subscene.setWidth(this.getWidth());

// Clear any existing stuff
root.getChildren().clear();
root.setStyle("-fx-background-color: rgba(0, 0, 0, 0);");
root.getChildren().add(camera);
camera.getTransforms().clear();

int xDataPoints = data.length;
int zDataPoints = data[0].length;

// Create data mesh
TriangleMesh mesh = new TriangleMesh();
for (int x = 0; x < xDataPoints; x++) {
for (int z = 0; z < zDataPoints; z++) {
// Invert the data as JavaFX meshes are positive-down, whereas we expect
// the plot to be positive-up
mesh.getPoints().addAll(x, (float) (-data[x][z]), z);
}
}

// Create faces from data mesh
for (int x = 0; x < xDataPoints - 1; x++) {
for (int z = 0; z < zDataPoints - 1; z++) {
int tl = x * zDataPoints + z; // top-left
int bl = x * zDataPoints + z + 1; // bottom-left
int tr = (x + 1) * zDataPoints + z; // top-right
int br = (x + 1) * zDataPoints + z + 1; // bottom-right

int offset = (x * (zDataPoints - 1) + z) * 8 / 2; // div 2 because we have u AND v in the list

// working
mesh.getFaces().addAll(bl, offset + 1, tl, offset + 0, tr, offset + 2);
mesh.getFaces().addAll(tr, offset + 2, br, offset + 3, bl, offset + 1);
}
}

// Create data mesh texture map
for (float x = 0; x < xDataPoints - 1; x++) {
for (float z = 0; z < zDataPoints - 1; z++) {
float x0 = x / xDataPoints;
float z0 = z / zDataPoints;
float x1 = (x + 1) / xDataPoints;
float z1 = (z + 1) / zDataPoints;

mesh.getTexCoords().addAll( //
x0, z0, // 0, top-left
x0, z1, // 1, bottom-left
x1, z1, // 2, top-right
x1, z1 // 3, bottom-right
);
}
}

// Create texture material
Image diffuseMap = createTexture(data);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(diffuseMap);

// Create & add mesh view
MeshView meshView = new MeshView(mesh);
meshView.setTranslateZ(-zDataPoints);
meshView.setMaterial(material);
meshView.setCullFace(CullFace.NONE);
meshView.setDrawMode(DrawMode.FILL);
meshView.setDepthTest(DepthTest.ENABLE);
root.getChildren().addAll(meshView);

double biggestAxisSize = xDataPoints;
double z = -(0.5 * biggestAxisSize) / Math.tan(0.5 * Math.toRadians(camera.getFieldOfView()));
camera.getTransforms().addAll(
new Translate(0, 0, -zDataPoints / 3.0),
new Rotate(-30, Rotate.X_AXIS),
new Translate(0, 0.5, z)
);
camera.setFarClip(biggestAxisSize * 200.0);
}

private Image createTexture(double[][] data) {
int width = data.length;
int height = data[0].length;

WritableImage wr = new WritableImage(width, height);
PixelWriter pw = wr.getPixelWriter();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
pw.setColor(x, y, Color.RED);
}
}
return wr;
}
}
}

最佳答案

修改cullFace property您的MeshView:

meshView.setCullFace(CullFace.NONE);

您还需要向场景添加环境光。表面的法线是自动确定的,如果法线背向光源,则使用的标量积将不是正值...

root.getChildren().add(new AmbientLight(Color.WHITE));

关于javafx - 在JavaFX中,如何为网格的反面着色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59282039/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com