适用于JavaFX全景查看器

时间:2015-06-28 10:24:17

标签: java javafx javafx-8 lighting javafx-3d

我目前正在尝试使用其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);
  }
}

1 个答案:

答案 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。如您所见,如果设置环境光,则视角完全消失。

Lights

测试代码:

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;
  }
}