JavaFX 3D 让节点面向/看着相机

问题描述 投票:0回答:1

所以我有一个显示分子的小应用程序。在角落里,我有第二个场景,显示轴和相对于主场景的轴旋转。在每个轴的末尾,我想要文本说明它是哪个轴,标签是 a、b、c(认为 x、y、z,但输入采用分数坐标)。

旋转场景时,我能够将 a、b、c 保持在正确的位置,它们通常面向(注视)相机,但当我跨过特定轴时它们会旋转。

[初始位置 - 标签方向正确] (https://i.stack.imgur.com/9LTQz.png) After rotating - labels flip

因此,标签是 MyLabels 扩展了 GridPane,其中包含文本,它们有一个 setTransforms 函数,可以给出查看结果、默认比例以及基于轴末端位置的平移。


public class MyLabel extends GridPane {
    public Point3D position;
    double scaleFactor =-0.05;
    Scale scale = new Scale(scaleFactor,scaleFactor,scaleFactor,0,0,0);
    Translate translate;
    public MyLabel(String message, Point3D position) {
        System.out.println("new label: " + message + " " + position);
        Text label = new Text(message);
        Font font = new Font("arial", 20);
        label.setFont(font);
        label.setCache(true);

        setAlignment(Pos.CENTER);

        this.position = position;


        CuboidMesh contentShape = new CuboidMesh(0,0, 0.01);
        GridPane.setHalignment(label, HPos.CENTER);
        add(label, 3, 1);

        double w = contentShape.getWidth() * 10; // more resolution
        double h = contentShape.getHeight() * 10;
        double d = contentShape.getDepth() * 10;
        final double W = 2 * d + 2 * w;
        final double H = 2 * d + h;

        ColumnConstraints col1 = new ColumnConstraints();
        col1.setPercentWidth(d * 100 / W);
        ColumnConstraints col2 = new ColumnConstraints();
        col2.setPercentWidth(w * 100 / W);
        ColumnConstraints col3 = new ColumnConstraints();
        col3.setPercentWidth(d * 100 / W);
        ColumnConstraints col4 = new ColumnConstraints();
        col4.setPercentWidth(w * 100 / W);
        getColumnConstraints().addAll(col1, col2, col3, col4);

        RowConstraints row1 = new RowConstraints();
        row1.setPercentHeight(d * 100 / H);
        RowConstraints row2 = new RowConstraints();
        row2.setPercentHeight(h * 100 / H);
        RowConstraints row3 = new RowConstraints();
        row3.setPercentHeight(d * 100 / H);
        getRowConstraints().addAll(row1, row2, row3);
        setPrefSize(W, H);

        setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
        translate = new Translate(this.position.getX(),this.position.getY(),this.position.getZ());
    }




    public void setTransforms(Transform affine) {
        try {
            getTransforms().setAll(affine);
            getTransforms().add(scale);
            getTransforms().add(translate);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

我看的功能是:

public static Affine lookAt(Point3D from, Point3D to, Point3D ydir) {

    Point3D zVec = to.subtract(from).normalize();
    Point3D xVec = ydir.normalize().crossProduct(zVec).normalize();
    Point3D yVec = zVec.crossProduct(xVec).normalize();

    Affine affine = new Affine(xVec.getX(), 0, zVec.getX(), from.getX(),
            xVec.getY(), yVec.getY(), zVec.getY(), from.getY(),
            xVec.getZ(), yVec.getZ(), zVec.getZ(), from.getZ());

    return  affine;


}

当相机移动时,我使用以下方法更新标签:

Point3D randomPoint = new Point3D(0,0,-20); //camera initially starts 0,0,-50
Point3D camera = cameraXform.localToScene(randomPoint);
myLabel.setTransforms(lookAt(myLabel.position,camera,new Point3D(0, 1,0)));

cameraXform 是包含两个相机(轴相机和主场景相机)的组,它有一个不断添加的变换,这就是鼠标移动时旋转发生的方式。


class XformCamera extends Group {
    Point3D px = new Point3D(1.0, 0.0, 0.0);
    Point3D py = new Point3D(0.0, 1.0, 0.0);
    Rotate r;
    Transform t = new Rotate();

    public XformCamera() {
        super();
    }
    public void rx(double angle) {
       // System.out.println("rx: " + angle);
        r = new Rotate(angle, px);
        this.t = t.createConcatenation(r);
        this.getTransforms().clear();
        this.getTransforms().addAll(t);
    }

    public void ry(double angle) {
        //System.out.println("ry: " + angle);
        r = new Rotate(angle, py);
        this.t = t.createConcatenation(r);
        this.getTransforms().clear();
        this.getTransforms().addAll(t);
    }


}

经过大量工作后,标签保持正确的平移,它们大部分时间面向眼睛,但偶尔会翻转(翻转发生得很快,但不是立即发生,即,它将面朝良好,然后对于大约 10 度的弧度)将完全翻转然后再次面对(翻转),直到大约 80 度后达到下一个 10 度疯狂。

我认为我需要做的是找出适合眼睛的方向(但是在二维中?),并确保在lookAt之后标签与其垂直,但我现在有点超出了我的工作深度出来了。

非常感谢任何帮助!

我尝试过使用 Fxyz,但是我很难找到任何有关它的文档。 我用过 localToScene、localToScreen、localToParent 但没有成功。 如果我将cameraXForm传递给它完美面对的标签,但是没有转换到正确的位置。 我也很高兴将标签放在场景顶部的 2d 中,并根据轴的位置更新它们的 x,y 坐标,为此我需要获取组中 3d 点的 2d 场景坐标.

3d label javafx-8 perspectivecamera openjfx
1个回答
0
投票

正确的方法是使用从 3D 锚点转换而来的浮动 2D 标签。

我尝试过使用 Fxyz

你有吗?因为我们的示例模块中有一个示例可以完全满足您的需求:

FXyz3D 中的浮动标签示例

此解决方案的重要说明:

  1. 在 2D 平面中进行裁剪会让你陷入困境。这个例子已经有护栏逻辑了。
  2. 您需要以某种方式在场景中维护 3D 点,以便哈希图具有对变换的引用。如果您稍后选择删除标签,您可能还想删除与其配对的 3D 点/对象。 (否则你可能会积累物体
  3. 您需要有一个场景布局,其中 2D 叠加不会尝试自动定位标签。

但是我很难找到任何有关它的文档。

嗯……当没有人付钱让你写所有这些东西然后免费赠送时,很难找到更多的空闲时间来制作精美的文档。 (这是对其他来到我们 github 抱怨的人的攻击) 然而,我们确实为大量非平凡示例制作了一个完全交互式的采样器应用程序:

FXyz3D 提供的交互式采样器

GLHF。其他 FXyz3D 人员都比我好。

© www.soinside.com 2019 - 2024. All rights reserved.