我目前正在尝试使用其3D功能在JavaFX中设置全景查看器。我认为我的几何形状是正确的(3D子场景,TriangleMesh等),但我正在与适当的光照作斗争。我需要的是实际上根本没有光照,只是几何上正确显示纹理图像的原始颜色。如果没有指定明确的光照,JavaFX似乎会引入一些不需要的默认光照,这让我很疯狂。
有人可以告诉我如何设置材料和光源以及其他相关的东西,如果我不想要任何照明而只是简单的图像(纹理)颜色吗?
编辑: 这是请求的代码示例。当盒子旋转时,由于照明,你可以清楚地看到盒子的角落。如果你可以关掉灯光,这些角落应该会消失。
import javafx.animation.Interpolator;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.image.Image;
import javafx.scene.layout.VBox;
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.stage.Stage;
import javafx.util.Duration;
public class SimplePanoViewer extends Application {
private static final int VIEWPORT_SIZE = 1200;
private static final double MODEL_SCALE_FACTOR = VIEWPORT_SIZE/2;
private static final String textureLoc = "http://www.f-lohmueller.de/pov_tut/backgrnd/im/Cubemap_2_2048x1536.jpg";
private Image texture;
private PhongMaterial texturedMaterial = new PhongMaterial();
private MeshView meshView = loadMeshView();
private MeshView loadMeshView() {
float[] points = {
-0.5f, -0.5f, -0.5f,
-0.5f, +0.5f, -0.5f,
+0.5f, +0.5f, -0.5f,
+0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, +0.5f,
-0.5f, +0.5f, +0.5f,
+0.5f, +0.5f, +0.5f,
+0.5f, -0.5f, +0.5f
};
float TX0 = 0f;
float TX1 = 1f/4f;
float TX2 = 2f/4f;
float TX3 = 3f/4f;
float TX4 = 1f;
float TY0 = 0f;
float TY1 = 1f/3f;
float TY2 = 2f/3f;
float TY3 = 1f;
float[] texCoords = {
TX0, TY1,
TX0, TY2,
TX1, TY2,
TX1, TY3,
TX2, TY3,
TX2, TY2,
TX3, TY2,
TX4, TY2,
TX4, TY1,
TX3, TY1,
TX2, TY1,
TX2, TY0,
TX1, TY0,
TX1, TY1,
};
int[] faces = {
0, 0, 1, 1, 5, 2, 5, 2, 4, 13, 0, 0, // 0
4, 13, 5, 2, 6, 5, 6, 5, 7, 10, 4, 13, // 1
7, 10, 6, 5, 2, 6, 2, 6, 3, 9, 7, 10, // 2
3, 9, 2, 6, 1, 7, 1, 7, 0, 8, 3, 9, // 3
0, 12, 4, 13, 7, 10, 7, 10, 3, 11, 0, 12, // 4
5, 2, 1, 3, 2, 4, 2, 4, 6, 5, 5, 2 // 5
};
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);
meshView.setTranslateY(VIEWPORT_SIZE / 2 * 9.0 / 16);
meshView.setTranslateZ(-VIEWPORT_SIZE );
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);
meshView.setCullFace(CullFace.NONE);
meshView.setDrawMode(DrawMode.FILL);
rotate.play();
meshView.setMaterial(texturedMaterial);
VBox layout = new VBox(
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);
scene3d.setFill(Color.rgb(10, 10, 40));
PerspectiveCamera camera = new PerspectiveCamera();
scene3d.setCamera(camera);
return scene3d;
}
private RotateTransition rotate3dGroup(Group group) {
RotateTransition rotate = new RotateTransition(Duration.seconds(30), 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) {
launch(args);
}
}
答案 0 :(得分:1)
我对JavaFX 3D不是一个坚实的专业,但我会尝试回答。 JavaFX 3D需要光才能显示透视图。如果关闭灯,则Subscene会变为黑色。
JavaFX中只有两个Lights,一个AmbientLight和一个PointLight。两者都可以添加到添加了meshview的组中。 JavaDoc说的是 AmbientLight :
环境光是一种似乎来自各个方向的光源
PointLight 获得此描述:
在空间中具有固定点并辐射光的光源 同样在各个方向远离自己。
如果没有Light添加到Scene或SubScene,它会添加一个从顶部照射到3D形状的默认PointLight。如果添加一个Light(环境或点),则删除默认值。
如果你想放置一个灯,那么你应该在你的构建场景方法中做到这一点。
private Group buildScene() {
meshView.setTranslateX(VIEWPORT_SIZE / 2);
meshView.setTranslateY(VIEWPORT_SIZE / 2 * 9.0 / 16);
meshView.setTranslateZ(-VIEWPORT_SIZE);
meshView.setScaleX(MODEL_SCALE_FACTOR);
meshView.setScaleY(MODEL_SCALE_FACTOR);
meshView.setScaleZ(MODEL_SCALE_FACTOR);
meshView.setCullFace(CullFace.NONE);
Group group = new Group(meshView);
AmbientLight ambient = new AmbientLight(); // default color white
ambient.setLightOn(true); // switch it off and everything is black
group.getChildren().add(ambient);
return group;
}
下面显示的灯是默认灯,PointerLight和AmbientLight。如您所见,如果设置环境光,则视角完全消失。
测试代码:
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*;
import javafx.stage.Stage;
public class Shapes3DViewer extends Application {
PhongMaterial material;
@Override
public void start(Stage stage) {
material = new PhongMaterial();
material.setDiffuseColor(Color.FIREBRICK);
material.setSpecularColor(Color.YELLOW);
PointLight pointLight = new PointLight(Color.WHITE);
pointLight.setTranslateX(100);
pointLight.setTranslateY(100);
pointLight.setTranslateZ(-300);
pointLight.setRotate(90);
AmbientLight ambient = new AmbientLight();
Group g1 = createSphereGroup(200, "Default light");
Group g2 = createSphereGroup(200, "Point light");
Group g3 = createSphereGroup(200, "Ambient light");
g2.getChildren().add(pointLight);
g3.getChildren().add(ambient);
SubScene s1 = createSubScene(g1, 500, 500);
SubScene s2 = createSubScene(g2, 500, 500);
SubScene s3 = createSubScene(g3, 500, 500);
HBox root = new HBox();
root.getChildren().addAll(s1, s2, s3);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private Group createSphereGroup(double radius, String text) {
Sphere c = new Sphere(radius);
c.setMaterial(material);
c.setDrawMode(DrawMode.FILL);
c.setTranslateX(radius * 1.33);
c.setTranslateY(radius * 1.33);
Label lbl = new Label(text);
lbl.setStyle("-fx-text-fill: red;-fx-font-size: 18pt;");
return new Group(c, lbl);
}
private SubScene createSubScene(Group group, double width, double height) {
SubScene s = new SubScene(group, width, height);
s.setCamera(new PerspectiveCamera());
s.setFill(Color.color(.1, .1, .1));
return s;
}
}