- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题
我想将漫反射贴图应用到 MeshView。当我将具有漫反射贴图的 Material 应用到 MeshView 时,它不可见。然而,应用于盒子的相同 Material 是可见的。
问题
要将漫反射贴图应用到 MeshView,我需要做什么?
代码
该代码生成带有随机噪声的图像。该图像用作 PhongMaterial 中的漫反射贴图。将显示图像,其上方是应用了 Material 的框,框上方是应用了 Material 的 MeshView(金字塔)。该 Material 在金字塔上不可见。您可以使用鼠标拖动进行旋转。
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);
}
}
截图
非常感谢您的帮助!
最佳答案
该形状由 6 个单一形状组成。四个三角形都交于 A 点。底部有一个矩形,因为它们是三角形,所以需要两个三角形来创建矩形。下图显示了该形状的俯 View 。
如您所见,我们有 5 分。因此必须将它们添加到 TriangleMesh 的 Points 中。一个点由三个浮点值 (x,y,z) 的元组组成。所以这个数组总是由 3, 6, 9,...,15 等大小组成。
如果您将图像作为网格物体的 Material (就像您所做的那样),则必须获取纹理坐标并将图像坐标添加到其中。但你在这里添加什么?这些是您想要设置为 Material 的图像的 2D 坐标。它从 (0.0, 0.0) (u0, v0) 开始,一直到 (1.0, 1.0) (u1, v1)。它是您想要在 3D 网格上显示的图像片段的 2D 坐标。由于您只有一张嘈杂的图像,因此您可以执行 0,0 到 1,1,但三角形需要 3 个点。
现在你必须做表面处理。这就像您想在形状线条之间的空间放置一些盘子。正如您已经看到的,您必须为三角形添加四 block ,为底部添加两 block 。
面是一个包含六个值的元组。因为我们画的是三角形,所以总是这样的:从点,到点,到点。所以这个元组由 6 个值组成。 p0、t0、p1、t1、p2、t2。这些值是点和纹理数组的索引。 p0指向点数组的第一个树元组,t0指向纹理坐标数组的前两个元组。
也许我的解释不完全正确,但我是这样理解的:
JavaFX 的默认摄像头是逆时针方向的,因此如果您将脸部逆时针方向放置,您的脸部正面将对摄像头可见。正面不支持,这是出于性能问题在 JavaFX 内部完成的。只要您不将剔除设置为背面,背面就不会用任何 Material 渲染。
要查看这个三角形的底部,相机必须改变它的视角,所以它是顺时针方向的。正面和背面也是同样的情况。
在您的示例中,我已经命名了这些点,因为现在您可以看到我首先渲染了哪些面以及最后渲染了哪些面。例如:
ABC 对我来说是第一个面,它是 A、B 和 C 点之间的三角形。这些点从 Material 图像坐标中获取纹理。
有关这些内容的更多信息,请访问 José Pereda 的博客:http://jperedadnr.blogspot.de/2015/01/creating-and-texturing-javafx-3d-shapes.html
希望您已经理解了所有内容,然后您将在下面找到我的解决方案。
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
float hs = s / 2;
// coordinates of the mapped image
float x0 = 0.0f;
float y0 = 0.0f;
float x1 = 1.0f;
float y1 = 1.0f;
TriangleMesh pyramidMesh = new TriangleMesh();
pyramidMesh.getPoints().addAll( //
0.0f, 0.0f, 0.0f, // A 0 Top of Pyramid
hs, h, -hs, // B 1
hs, h, hs, // C 2
-hs, h, hs, // D 3
-hs, h, -hs // E 4
);
pyramidMesh.getTexCoords().addAll( //
x0, y0, // 0
x0, y1, // 1
x1, y0, // 2
x1, y1 // 3
);
pyramidMesh.getFaces().addAll(// index of point, index of texture, index of point, index of texture, index of point, index of texture
0, 0, 1, 1, 2, 3, // ABC (counter clockwise)
0, 0, 2, 1, 3, 3, // ACD (counter clockwise)
0, 0, 3, 1, 4, 3, // ADE (counter clockwise)
0, 0, 4, 1, 1, 3, // AEB (counter clockwise)
4, 0, 3, 1, 2, 3, // EDC (Bottom first triangle clock wise)
2, 0, 1, 1, 4, 3 // CBE (Bottom second triangle clock wise)
);
MeshView pyramid = new MeshView();
pyramid.setMesh(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);
}
}
关于javafx - 为什么漫反射贴图没有应用于我的 MeshView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31110292/
问题 我想将漫反射贴图应用到 MeshView。当我将具有漫反射贴图的 Material 应用到 MeshView 时,它不可见。然而,应用于盒子的相同 Material 是可见的。 问题 要将漫反射
我想在 JavaFX 中的 MeshView 上显示 3D 图形。因为我想构建一个简单的模型查看器,所以为了清晰起见,我创建了选项卡。其中一个包含一个组 (meshGroup),我在其中添加了一个 S
我正在尝试使用 phongmaterial 将图像应用到我的 meshview 立方体,但屏幕上只显示没有颜色的黑色立方体。它曾经与 Box 和立方体一起工作,但现在也不能与它们一起工作。 还有,谁能
我正在为 JavaFX 使用 JCSG 库。 我有一些 MeshView 对象,我想将它们转换为 CSG 对象,有什么办法可以实现吗? 最佳答案 组合 javafx.scene.shape.Mesh
我是一名优秀的程序员,十分优秀!