本文介紹了如何給三角網(wǎng)格中的一些三角形上色?的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!
問(wèn)題描述
我想用不同的顏色給TriangleMesh的一些三角形上色。
執(zhí)行此操作的最簡(jiǎn)單方法是什么,甚至在fxml文件中也是可能的?
Java代碼:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.scene.layout.Pane;
import javafx.scene.shape.MeshView;
import javafx.stage.Stage;
import java.io.IOException;
public class ColoredMesh extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(
ColoredMesh.class.getResource(
"mesh.fxml"
)
);
MeshView meshView = fxmlLoader.load();
// mesh.setDrawMode(DrawMode.LINE);
meshView.setTranslateX(-200);
meshView.setTranslateY(400);
meshView.setRotate(90);
Camera camera = new PerspectiveCamera();
camera.setRotate(90);
Scene scene = new Scene(new Pane(meshView), 800, 400);
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
多邊形/棱錐體/三角網(wǎng)格文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.MeshView?>
<?import javafx.scene.shape.TriangleMesh?>
<MeshView>
<mesh>
<TriangleMesh>
<points>
0 100 100
100 100 0
0 100 -100
-100 100 0
0 0 0
</points>
<texCoords>
0 0
</texCoords>
<faces>
0 0 4 0 1 0
1 0 4 0 2 0
2 0 4 0 3 0
3 0 4 0 0 0
0 0 1 0 2 0
0 0 2 0 3 0
</faces>
</TriangleMesh>
</mesh>
</MeshView>
推薦答案
我猜這可能已作為重復(fù)項(xiàng)關(guān)閉(有關(guān)潛在重復(fù)項(xiàng)的引用,請(qǐng)參閱參考資料部分)。
然而,我認(rèn)為這個(gè)問(wèn)題的框架很有趣,而且非常獨(dú)特,它使用FXML定義了大部分模型,所以我想我應(yīng)該根據(jù)答案進(jìn)行調(diào)整。
高級(jí)步驟
-
您需要提供一個(gè)具有擴(kuò)散映射的PhongMaterial,該圖像將成為模型的紋理。
您需要在模型中定義映射到擴(kuò)散映射圖像(它是0到1范圍內(nèi)的比例映射)中的位置的紋理坐標(biāo)。
定義面時(shí),需要指定紋理貼圖中的索引,該索引將用于對(duì)面的頂點(diǎn)進(jìn)行著色。
完整的解釋超出了我現(xiàn)在準(zhǔn)備寫(xiě)的范圍,但我建議您參考其他資源,如果您需要,可以在那里找到更多信息。
輸出
這被渲染為gif,所以保真度不高,PC上的實(shí)際輸出看起來(lái)更好,gif輸出的速度大大加快,但它確實(shí)表明了解決方案的作用。
texture.png
ColoredMesh.java
加載帶紋理的模型并圍繞X和Y軸為其設(shè)置動(dòng)畫(huà)。
import javafx.animation.*;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Point3D;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.paint.*;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
public class ColoredMesh extends Application {
private static final Color INDIA_INK = Color.rgb(60,61,76);
private static final Color AMBIENT_GRAY = Color.rgb(100, 100, 100);
private static final Duration ROTATION_STEP_TIME = Duration.seconds(5);
@Override
public void start(Stage stage) throws IOException {
MeshView meshView = loadModel();
Scene scene = createScene(meshView);
stage.setScene(scene);
stage.show();
animateNode(meshView);
}
private Scene createScene(MeshView meshView) {
PerspectiveCamera camera = new PerspectiveCamera();
AmbientLight ambientLight = new AmbientLight(AMBIENT_GRAY);
Scene scene = new Scene(
new Group(
ambientLight,
meshView
),
200, 200,
INDIA_INK
);
scene.setCamera(camera);
return scene;
}
private MeshView loadModel() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(
ColoredMesh.class.getResource(
"pyramid-mesh.fxml"
)
);
MeshView meshView = fxmlLoader.load();
meshView.setTranslateX(100);
meshView.setTranslateY(40);
meshView.setTranslateZ(100);
// We have defined the material in the fxml which creates the MeshView.
// However, I leave this commented code here to show how the material
// can be defined in Java rather than FXML, if that were preferable.
// texture(meshView);
return meshView;
}
private void texture(MeshView meshView) {
PhongMaterial texturedMaterial = new PhongMaterial();
texturedMaterial.setDiffuseMap(
new Image(
ColoredMesh.class.getResource(
"texture.png"
).toExternalForm()
)
);
meshView.setMaterial(texturedMaterial);
}
private void animateNode(MeshView meshView) {
Animation rotateY = createRotationAnimation(Rotate.Y_AXIS, meshView);
Animation rotateX = createRotationAnimation(Rotate.X_AXIS, meshView);
rotateY.setOnFinished(e -> rotateX.play());
rotateX.setOnFinished(e -> rotateY.play());
rotateY.play();
}
private Animation createRotationAnimation(Point3D axis, Node node) {
RotateTransition animation = new RotateTransition(
ROTATION_STEP_TIME,
node
);
animation.setAxis(axis);
animation.setFromAngle(0);
animation.setToAngle(360);
return animation;
}
public static void main(String[] args) {
launch(args);
}
}
金字塔-Mesh.fxml
紋理是定義為為網(wǎng)格節(jié)點(diǎn)MeshView指定的PhongMaterial的漫反射貼圖的圖像。
在本例中,材料是在FXML中定義的,但如果您愿意,也可以在代碼中進(jìn)行定義(示例Java代碼包含一個(gè)注釋掉的部分來(lái)執(zhí)行此操作)。
網(wǎng)格中的紋理坐標(biāo)定義了紋理圖像中每個(gè)顏色樣本的中點(diǎn)。
對(duì)于基于三角形模型的金字塔整體,使用了六個(gè)三角形。對(duì)于底面,有兩個(gè)三角形,但它們的顏色都相同,因此只需要五個(gè)紋理坐標(biāo)就可以為每個(gè)面實(shí)現(xiàn)純色。
在定義面時(shí),每個(gè)對(duì)頂點(diǎn)的引用后跟一個(gè)對(duì)紋理坐標(biāo)的引用。每個(gè)三角面被定義為對(duì)所有頂點(diǎn)使用相同的紋理坐標(biāo),這將為面生成與紋理圖像中該紋理坐標(biāo)處的顏色相匹配的統(tǒng)一純色。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.MeshView?>
<?import javafx.scene.shape.TriangleMesh?>
<?import javafx.scene.paint.PhongMaterial?>
<?import javafx.scene.image.Image?>
<MeshView>
<material>
<PhongMaterial>
<diffuseMap>
<Image url="@texture.png"/>
</diffuseMap>
</PhongMaterial>
</material>
<mesh>
<TriangleMesh>
<points>
0 100 100
100 100 0
0 100 -100
-100 100 0
0 0 0
</points>
<texCoords>
0.1 0.5
0.3 0.5
0.5 0.5
0.7 0.5
0.9 0.5
</texCoords>
<faces>
0 0 4 0 1 0
1 1 4 1 2 1
2 2 4 2 3 2
3 3 4 3 0 3
0 4 1 4 2 4
0 4 2 4 3 4
</faces>
</TriangleMesh>
</mesh>
</MeshView>
TextureMaker.java
您可以以任何您想要的方式生成紋理圖像。
對(duì)于本演示,我編寫(xiě)了一個(gè)小程序,該程序從在JavaFX中創(chuàng)建的快照創(chuàng)建圖像。
如果有興趣,這是創(chuàng)建紋理的代碼,但不一定要使用它來(lái)運(yùn)行演示。
該概念稱(chēng)為T(mén)extureAtlas。
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class TextureMaker extends Application {
private static final int SWATCH_SIZE = 10;
private static final Color colors[] = {
Color.RED,
Color.GREEN,
Color.BLUE,
Color.MAGENTA,
Color.CYAN
};
@Override
public void start(Stage stage) throws IOException {
Rectangle[] colorSwatches = Arrays.stream(colors)
.map(this::createColoredRect)
.toArray(Rectangle[]::new);
FlowPane flowPane = new FlowPane(colorSwatches);
flowPane.setPrefSize(colors.length * SWATCH_SIZE, SWATCH_SIZE);
Scene scene = new Scene(
flowPane,
Color.rgb(60,61,76)
);
Image textureImage = scene.snapshot(null);
File textureFile = new File("texture.png");
ImageIO.write(
SwingFXUtils.fromFXImage(textureImage, null),
"png",
textureFile
);
System.out.println("Wrote: " + textureFile.getAbsolutePath());
stage.setScene(scene);
stage.show();
}
public Rectangle createColoredRect(Color color) {
return new Rectangle(SWATCH_SIZE,SWATCH_SIZE, color);
}
public static void main(String[] args) {
launch(args);
}
}
此實(shí)現(xiàn)創(chuàng)建一個(gè)圖像并將其保存到磁盤(pán),但如果需要,您可以在主應(yīng)用程序中動(dòng)態(tài)創(chuàng)建該圖像,而無(wú)需將其保存到磁盤(pán)。鏈接的類(lèi)似問(wèn)題中有這種方法的演示。
關(guān)于此解決方案
上述解決方案不是任意給任何給定網(wǎng)格上色的方法的通用答案。
相反,它更專(zhuān)注于回答特定問(wèn)題:
如何為您的問(wèn)題中定義的金字塔表面上色,
在fxml中定義盡可能多的數(shù)據(jù),并且不使用
外部庫(kù)?
關(guān)于復(fù)雜模型和重復(fù)使用預(yù)制模型的建議
對(duì)于復(fù)雜模型,我建議使用其他軟件支持的標(biāo)準(zhǔn)3D格式(例如.obj或.stl),而不是用FXML定義網(wǎng)格數(shù)據(jù)(面/頂點(diǎn)/紋理坐標(biāo))。
Web上有以常見(jiàn)格式提供的預(yù)先創(chuàng)建的模型(但不包括fxml)。此類(lèi)模型可以附帶必要的圖像貼圖和紋理坐標(biāo)定義來(lái)對(duì)其進(jìn)行著色。
您可以使用用于各種3D模型格式的第三方導(dǎo)入器庫(kù)將這些模型導(dǎo)入到JavaFX中。如果您進(jìn)行搜索,可以在Web上找到這些JavaFX導(dǎo)入器庫(kù),例如Interactive Mesh和f(X)yz庫(kù)。
相關(guān)問(wèn)題
-
Coloring individual triangles in a triangle mesh on javafx
正如Jose所指出的:這實(shí)際上是啟發(fā)FXyz3D中TexturedMesh的答案。
-
How to render 3D graphics properly
Jose對(duì)這個(gè)關(guān)于魔方覆蓋的問(wèn)題的回答非常適合您的應(yīng)用程序,盡管問(wèn)題標(biāo)題是通用的。
How to create a cube with all faces of different colors in JavaFX
applying texture to mesh in javafx
使用第三方庫(kù)FXyz3D回答,其功能類(lèi)似于TexturedMesh。
How to create a cube with all faces of different colors in JavaFX
Create a cube using different textures in JavaFX
How to create such shape using javaFx TriangleMesh?
強(qiáng)烈推薦理解紋理3D網(wǎng)格的教程
有一個(gè)非常好的教程(比我能想到的任何教程都好)就是Create 3D Shapes using MeshView。
本教程將圖像映射到棱錐體的表面,就像您問(wèn)題中的網(wǎng)格。它使用照片圖像,但在您的情況下,您將使用不同的純色區(qū)域。請(qǐng)?zhí)貏e查看紋理坐標(biāo)部分。
點(diǎn)擊教程中的圖像,它將顯示一個(gè)將紋理坐標(biāo)映射到圖像上的整齊覆蓋。這確實(shí)有助于可視化正在發(fā)生的事情。
這篇關(guān)于如何給三角網(wǎng)格中的一些三角形上色?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,