龙空技术网

RubikFX:用JavaFX 3D解决魔方难题(3)

刀笔小周 74

前言:

当前朋友们对“java读取3d模型”都比较关注,姐妹们都需要分析一些“java读取3d模型”的相关资讯。那么小编同时在网摘上网罗了一些有关“java读取3d模型””的相关知识,希望各位老铁们能喜欢,看官们快快来了解一下吧!

RubikFX, Lite Version

-----------------------------------------------------------------

魔方,精简版

后面我们将加入更多的特性,但是现在我们创建一个JavaFX应用,使用BorderPane组件,在Pane控件中添加内容,包含按钮的执行旋转功能的工具条。

public class TestRubikFX extends Application {                    private final BorderPane pane=new BorderPane();          private Rubik rubik;                    @Override          public void start(Stage stage) {                    rubik=new Rubik();                    // create toolbars                    //创建工具条,在上下左右四个方向创建4个工具条                    ToolBar tbTop=new ToolBar(new Button("U"),new Button("Ui"),new Button("F"),                                                                                    new Button("Fi"),new Separator(),new Button("Y"),                                                                                    new Button("Yi"),new Button("Z"),new Button("Zi"));                    pane.setTop(tbTop);                    ToolBar tbBottom=new ToolBar(new Button("B"),new Button("Bi"),new Button("D"),                                                                                             new Button("Di"),new Button("E"),new Button("Ei"));                    pane.setBottom(tbBottom);                    ToolBar tbRight=new ToolBar(new Button("R"),new Button("Ri"),new Separator(),                                                                                            new Button("X"),new Button("Xi"));          //工具条自身方向的设定                    tbRight.setOrientation(Orientation.VERTICAL);                    pane.setRight(tbRight);                    ToolBar tbLeft=new ToolBar(new Button("L"),new Button("Li"),new Button("M"),                                                                                     new Button("Mi"),new Button("S"),new Button("Si"));                    tbLeft.setOrientation(Orientation.VERTICAL);          //工具条自身方向的设定                    pane.setLeft(tbLeft);                                        pane.setCenter(rubik.getSubScene());                                        pane.getChildren().stream()                               .filter(n->(n instanceof ToolBar))                               .forEach(tb->{                                         ((ToolBar)tb).getItems().stream()                                                   .filter(n->(n instanceof Button))                                                   .forEach(n->((Button)n).setOnAction(e->rubik.rotateFace(((Button)n).getText())));                               });                    rubik.isOnRotation().addListener((ov,b,b1)->{                               pane.getChildren().stream()                               .filter(n->(n instanceof ToolBar))                               .forEach(tb->tb.setDisable(b1));                    });                    final Scene scene = new Scene(pane, 880, 680, true);                    scene.setFill(Color.ALICEBLUE);                    stage.setTitle("Rubik's Cube - JavaFX3D");                    stage.setScene(scene);                    stage.show();          } }

下图就是我们完成后的样子。

图四

如果你想对这个应用进行深入的研究,你能够在我的GitHub上找到源代码。

网址如下:

提示你,首先需要添加3DViewer的jar包。

如何运作?举个例子, “F”旋转,我们在rot中应用

// rotate cube indexes   //旋转立方体顺序索引        rot.turn(btRot);        // get new indexes in terms of blocks numbers from original order //依据原始顺序的Block编号得到新的顺序索引        reorder=rot.getCube();

使用rot.printCube()方法,我们可以得到旋转前(order)和旋转后(reorder)小立方体的编号

order: 50 51 52 49 54 53 59 48 46 || 58 55 60 57 62 61 47 56 63 || 67 64 69 66 71 70 68 65 72

reorder: 59 49 50 48 54 51 46 53 52 || 58 55 60 57 62 61 47 56 63 || 67 64 69 66 71 70 68 65 72

通过比对列表和获取差异项,我们可以知道哪些小立方体必须旋转,当然我们需要添加中间立方体的编号(54),它在列表中保持不变,但是它也应该被旋转。所以我们为9个立方体创建列表层。

// select cubies to rotate: those in reorder different from order.//选择被旋转的立方体,所有那些新序号与老序号不同的        AtomicInteger index = new AtomicInteger();        layer=order.stream()                  .filter(o->!Objects.equals(o, reorder.get(index.getAndIncrement())))                  .collect(Collectors.toList());        // add central cubie        //加入中间立方体        layer.add(0,reorder.get(Utils.getCenter(btRot)));        // set rotation axis           //设置旋转轴         axis=Utils.getAxis(btRot);

Utils是一个管理旋转类型数值的类,举个例子。

public static Point3D getAxis(String face){                    Point3D p=new Point3D(0,0,0);                    switch(face.substring(0,1)){                               case "F":                                 case "S":  p=new Point3D(0,0,1);                                                       break;                    }                    return p;          }                    public static int getCenter(String face){                    int c=0;                    switch(face.substring(0,1)){                               case "F":  c=4;  break;                    }                    return c;          }

当我们获得了小立方体和旋转轴,现在需要考虑旋转监听器如何工作了。在时间轴中,(预定义)一次EASE_BOTH插值角度增加从0到90度,所以角度增量在开始时比较小,中间变大,结束时又变小。下面是一种可行的增量变化表:

0.125º-3º-4.6º-2.2º-2.48º-...-2.43º-4.78º-2.4º-2.4º-0.55º。对于在angNew中的每个值,监听者rotMap对于小立方体的每一层都会进行一个小的旋转。在HashMap表中,隶属于小立方体的meshviews面,将进行一个相对于前一个Affine矩阵的旋预旋转。

/* Listener to perform an animated face rotation */                     rotMap=(ov,angOld,angNew)->{                                mapMeshes.forEach((k,v)->{                                         layer.stream().filter(l->k.contains(l.toString()))                                                   .findFirst().ifPresent(l->{                                                             Affine a=new Affine(v.getTransforms().get(0));                                                             a.prepend(new Rotate(angNew.doubleValue()-angOld.doubleValue(),axis));                                                             v.getTransforms().setAll(a);                                                   });                               });                    };

在600毫秒内,我们将对40个meshview面进行30到40次小旋转。最后,在旋转完成后,我们只需在最后的小立方体列表中更新顺序,如此我们又可以进行下一次旋转。

魔方—完整版

添加更多的特性

现在我们取得了一个很基础的基于JavaFX应用的作品,现在可以添加更多地特性,例如图形箭头和旋转预览,在旋转执行前显示旋转方向。

标签: #java读取3d模型