シーンには何も登場しませんでした
あなたのサンプルメッシュは私にとってはOKでした。
おそらく、カメラが正しく設定されていなかったか、メッシュが見えるようにスケーリングされていませんでした。
サンプル メッシュはあまり機能しません。1 つの三角形がカメラの方向を向き、2 つ目の三角形がカメラの反対側を向いています。
また、テクスチャなし(ワイヤーフレームモデルが欲しい)で作成することは可能ですか?
はい、メッシュ ビューの DrawModeをLineに設定します。
サンプルプログラムの説明
顔の順序を変更して、両方が同じ方向を向くようにしました。これにより、1 つの三角形が視聴者の方を向いており、1 つの三角形が視聴者から離れているのではなく、視聴者の方を向いている正方形が得られます。
int[] faces = {
2, 2, 1, 1, 0, 0,
2, 2, 3, 3, 1, 1
};
また、テクスチャ マップを変更する必要があります (上記のフェース配列がテクスチャの正しい方向を取得するため、逆さまにならないようにします)。
float[] texCoords = {
1, 1,
1, 0,
0, 1,
0, 0
};
カルバック コントロールを設定し、モデルの回転をアニメートして、三角形の「裏側」(黒) が見えるようにし、何がレンダリングされているかが明確になるようにしました。また、テクスチャまたはワイヤフレーム モードの拡散マップ (一部の大理石) を切り替える機能も追加しました。
サンプル プログラムの出力
サンプルプログラム
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.CheckBox;
import javafx.scene.image.Image;
import javafx.scene.layout.VBox;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
public class InlineModelViewer extends Application {
private static final int VIEWPORT_SIZE = 800;
private static final double MODEL_SCALE_FACTOR = 40;
private static final double MODEL_X_OFFSET = 0;
private static final double MODEL_Y_OFFSET = 0;
private static final double MODEL_Z_OFFSET = VIEWPORT_SIZE / 2;
private static final String textureLoc = "https://www.sketchuptextureclub.com/public/texture_f/slab-marble-emperador-cream-light-preview.jpg";
private Image texture;
private PhongMaterial texturedMaterial = new PhongMaterial();
private MeshView meshView = loadMeshView();
private MeshView loadMeshView() {
float[] points = {
-5, 5, 0,
-5, -5, 0,
5, 5, 0,
5, -5, 0
};
float[] texCoords = {
1, 1,
1, 0,
0, 1,
0, 0
};
int[] faces = {
2, 2, 1, 1, 0, 0,
2, 2, 3, 3, 1, 1
};
TriangleMesh mesh = new TriangleMesh();
mesh.getPoints().setAll(points);
mesh.getTexCoords().setAll(texCoords);
mesh.getFaces().setAll(faces);
return new MeshView(mesh);
}
private Group buildScene() {
meshView.setTranslateX(VIEWPORT_SIZE / 2 + MODEL_X_OFFSET);
meshView.setTranslateY(VIEWPORT_SIZE / 2 * 9.0 / 16 + MODEL_Y_OFFSET);
meshView.setTranslateZ(VIEWPORT_SIZE / 2 + MODEL_Z_OFFSET);
meshView.setScaleX(MODEL_SCALE_FACTOR);
meshView.setScaleY(MODEL_SCALE_FACTOR);
meshView.setScaleZ(MODEL_SCALE_FACTOR);
return new Group(meshView);
}
@Override
public void start(Stage stage) {
texture = new Image(textureLoc);
texturedMaterial.setDiffuseMap(texture);
Group group = buildScene();
RotateTransition rotate = rotate3dGroup(group);
VBox layout = new VBox(
createControls(rotate),
createScene3D(group)
);
stage.setTitle("Model Viewer");
Scene scene = new Scene(layout, Color.CORNSILK);
stage.setScene(scene);
stage.show();
}
private SubScene createScene3D(Group group) {
SubScene scene3d = new SubScene(group, VIEWPORT_SIZE, VIEWPORT_SIZE * 9.0/16, true, SceneAntialiasing.BALANCED);
scene3d.setFill(Color.rgb(10, 10, 40));
scene3d.setCamera(new PerspectiveCamera());
return scene3d;
}
private VBox createControls(RotateTransition rotateTransition) {
CheckBox cull = new CheckBox("Cull Back");
meshView.cullFaceProperty().bind(
Bindings.when(
cull.selectedProperty())
.then(CullFace.BACK)
.otherwise(CullFace.NONE)
);
CheckBox wireframe = new CheckBox("Wireframe");
meshView.drawModeProperty().bind(
Bindings.when(
wireframe.selectedProperty())
.then(DrawMode.LINE)
.otherwise(DrawMode.FILL)
);
CheckBox rotate = new CheckBox("Rotate");
rotate.selectedProperty().addListener(observable -> {
if (rotate.isSelected()) {
rotateTransition.play();
} else {
rotateTransition.pause();
}
});
CheckBox texture = new CheckBox("Texture");
meshView.materialProperty().bind(
Bindings.when(
texture.selectedProperty())
.then(texturedMaterial)
.otherwise((PhongMaterial) null)
);
VBox controls = new VBox(10, rotate, texture, cull, wireframe);
controls.setPadding(new Insets(10));
return controls;
}
private RotateTransition rotate3dGroup(Group group) {
RotateTransition rotate = new RotateTransition(Duration.seconds(10), group);
rotate.setAxis(Rotate.Y_AXIS);
rotate.setFromAngle(0);
rotate.setToAngle(360);
rotate.setInterpolator(Interpolator.LINEAR);
rotate.setCycleCount(RotateTransition.INDEFINITE);
return rotate;
}
public static void main(String[] args) {
System.setProperty("prism.dirtyopts", "false");
launch(args);
}
}
自分の 3D モデルを作成する方法を誰か説明してもらえますか
これは、StackOverflow にとっては広すぎる質問です。そういうもので卒業証書を出す大学や美大があります。
APIの残りの部分がdoubleを使用しているのに、Mesh.setAllがfloat []を取る理由を誰か説明できますか?
JavaFX 3D 実装は、グラフィック ハードウェア (DirectX や OpenGL など) と通信するネイティブ API のラッパーを提供します。これらの API は、倍精度ではなく浮動小数点精度で動作します。API で直接使用float[]
することは、メッシュ モデル データをより効率的に保存し、使用double[]
した場合よりも下層のグラフィックス API に直接マップできることを意味しますObservableList<Double>
。