如何在JavaFX 2.0演示中创建视频墙? [英] How to create a Video Wall like in the JavaFX 2.0 demo?

查看:265
本文介绍了如何在JavaFX 2.0演示中创建视频墙?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在这里创建像JavaFX 2.0演示中的视频墙:



。使用左/右/鼠标中键进行导航。



如果你想玩一个完整的球体,你可以使用它:

  //全球
for(double angle1 = -Math.PI; angle1< = Math.PI; angle1 + = 0.15) {
for(double angle2 = -Math.PI; angle2< = Math.PI; angle2 + = 0.15){

double x = r * Math.sin(angle1)* Math名为.cos(angle2);
double y = r * Math.sin(angle1)* Math.sin(angle2);
double z = r * Math.cos(angle1);

c = createImageView();

c.setTranslateX(x);
c.setTranslateY(y);
c.setTranslateZ(z);

旋转rx = new Rotate();
rx.setAxis(Rotate.Y_AXIS);
rx.setAngle(Math.toDegrees(-angle1));

c.getTransforms()。addAll(rx);

world.getChildren()。add(c);
}
}

看起来像这样:





但如上所述,我还没有弄清楚如何旋转所有瓷砖以便它们看向中心。他们需要平等分配。但这只是为了娱乐和偏离主题。






因为它是我问题视频的一部分,所以它只是一个保持平行过渡列表以创建图块的建立动画的问题。底行现在有一个反射。





扩展代码:

 公共类VideoWall扩展申请{

随机rand = new Random();

Group root = new Group();
PerspectiveCamera相机;

private static final double CAMERA_INITIAL_DISTANCE = -850;
private static final double CAMERA_NEAR_CLIP = 0.1;
private static final double CAMERA_FAR_CLIP = 10000.0;

图片[] images = new Image [] {
new Image(http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/ 320px-Siberischer_tiger_de_edit02.jpg),
新图片(http://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/White_Lion.jpg/320px-White_Lion.jpg),
new Image(http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Lion_female.jpg/319px-Lion_female.jpg)

};

List< ParallelTransition> transitionList = new ArrayList<>();

public VideoWall(){

}
public static void main(String [] args){
launch(args);
}

/ **
*使用随机图像创建ImageView。
* @return
* /
private ImageView createImageView(){

Image image = images [rand.nextInt(images.length)];

ImageView c = new ImageView(image);

c.setFitWidth(140);
c.setFitWidth(100);
c.setPreserveRatio(true);

返回c;
}

@Override
public void start(Stage primaryStage){

//构建相机
camera = new PerspectiveCamera(true) ;
camera.setNearClip(CAMERA_NEAR_CLIP);
camera.setFarClip(CAMERA_FAR_CLIP);
camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);

//我们显示任何节点(imageview,webview等)
节点节点;

//墙。度数取决于距离,图像大小,翻译起点等等,所以这些值恰好符合
double ringBeginDeg = -30;
double ringEndDeg = 38;

double r = 1300;
double yOffset = 80; //每个图像行的偏移量
double yOffsetInitial = 120; //初始y偏离floor

int min = -3;
int max = 3;

for(double angle1 = Math.toRadians(ringBeginDeg); angle1< Math.toRadians(ringEndDeg); angle1 + = 0.08)
{

double angle2 = Math.PI;

for(int i = min; i< = max; i ++)
{

double x = r * Math.sin(angle1)* Math。 COS(angle2);
// double y = r * Math.sin(angle1)* Math.sin(angle2);
double z = r * Math.cos(angle1);

node = createImageView();

node.setTranslateX(x);
node.setTranslateY(yOffset * i - yOffsetInitial);
node.setTranslateZ(z);

//向观察者位置旋转
旋转rx = new旋转();
rx.setAxis(Rotate.Y_AXIS);
rx.setAngle(Math.toDegrees(-angle1));

node.getTransforms()。addAll(rx);

//底行反射
if(i == max){
Reflection refl = new Reflection();
refl.setFraction(0.8f);
node.setEffect(refl);
}

//使用转换来构建墙
node.setVisible(false);
transitionList.add(createTransition(node));

root.getChildren()。add(node);

}

}

场景场景=新场景(root,1600,900,Color.BLACK);

primaryStage.setScene(scene);
primaryStage.show();

scene.setCamera(相机);

AnimationTimer timer = createAnimation();
timer.start();

}

private AnimationTimer createAnimation(){

Collections.sort(transitionList,new Comparator< ParallelTransition>(){

@Override
public int compare(ParallelTransition arg0,ParallelTransition arg1){

//右下角到左上角
Point2D ref = new Point2D(1000,1000);
Point2D pt0 = new Point2D(arg0.getNode()。getTranslateX(),arg0.getNode()。getTranslateY());
Point2D pt1 = new Point2D(arg1.getNode()。getTranslateX() ,arg1.getNode()。getTranslateY());

返回Double.compare(ref.distance(pt0),ref.distance(pt1));

//底行首先
//返回-Double.compare(arg0.getNode()。getTranslateY(),arg1.getNode()。getTranslateY());

}

});


AnimationTimer timer = new AnimationTimer(){

long last = 0;

@Override
public void handle(现在很长){

// if((现在 - 最后)> 1_000_000_000)
if(( now - 40_000_000)
{
if(transitionList.size()> 0){

ParallelTransition t = transitionList.remove(0);
t.getNode()。setVisible(true);
t.play();

}
last = now;

}

if(transitionList.size()== 0){
stop();
}
}

};

返回计时器;
}

private ParallelTransition createTransition(最终节点节点){

Path path = new Path();
path.getElements()。add(new MoveToAbs(node,node.getTranslateX() - 1000,node.getTranslateY() - 900));
path.getElements()。add(new LineToAbs(node,node.getTranslateX(),node.getTranslateY()));

持续时间= Duration.millis(1500);

PathTransition pt = new PathTransition(持续时间,路径,节点);

RotateTransition rt = new RotateTransition(duration,node);
rt.setByAngle(720);
rt.setAutoReverse(true);

ParallelTransition parallelTransition = new ParallelTransition();
parallelTransition.setNode(node);
parallelTransition.getChildren()。addAll(pt,rt);

返回parallelTransition;

}

公共静态类MoveToAbs扩展MoveTo {

public MoveToAbs(Node node,double x,double y){
super (x - node.getLayoutX()+ node.getLayoutBounds()。getWidth()/ 2,y - node.getLayoutY()+ node.getLayoutBounds()。getHeight()/ 2);
}

}

公共静态类LineToAbs扩展LineTo {

public LineToAbs(Node node,double x,double y){
super(x - node.getLayoutX()+ node.getLayoutBounds()。getWidth()/ 2,y - node.getLayoutY()+ node.getLayoutBounds()。getHeight()/ 2);
}

}

}


How do you create a video wall like in the JavaFX 2.0 demo here:

https://www.youtube.com/watch?v=UXSmJYFrulY#t=411

For a start it doesn't have to be videos, it can be images as well. All I'd like to have is to place the nodes like they are in the video, i. e. in a curved shape like the insides of a cylinder or a sphere.

Or is the source of that demo available somewhere?

Thank you very much.

解决方案

I researched and found a very awesome site with the relevant information:

http://paulbourke.net/geometry/transformationprojection/

The relevant part was the Coordinate System Transformation, in particular the equations for converting between cartesian and spherical coordinates.

double x = r * Math.sin(angle1) * Math.cos(angle2);
double y = r * Math.sin(angle1) * Math.sin(angle2);
double z = r * Math.cos(angle1);

In my example below y isn't used from the formula, since the image rows are stacked.

Note: By using these formulas in 2 nested for-loops from -Math.PI to Math.PI you can lay out the nodes around a sphere. The difficult part regarding the full sphere was to rotate the nodes towards the center, that one I couldn't figure out.

Since I wasn't familiar with Java3D I also checked out the Building a 3D Sample Application.

In the end I got a video wall, the code is reduced to this:

public class VideoWall extends Application {

    Random rand = new Random();

    Group root = new Group();
    PerspectiveCamera camera;

    private static final double CAMERA_INITIAL_DISTANCE = -850;
    private static final double CAMERA_NEAR_CLIP = 0.1;
    private static final double CAMERA_FAR_CLIP = 10000.0;

    Image[] images = new Image[] {
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg"),
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/White_Lion.jpg/320px-White_Lion.jpg"),
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Lion_female.jpg/319px-Lion_female.jpg")

    };

    public VideoWall(){

    }
    public static void main(String[] args) {
        launch(args);
    }

    /**
     * Create ImageView with random Image.
     * @return
     */
    private ImageView createImageView() {

        Image image = images[ rand.nextInt(images.length)];

        ImageView c = new ImageView( image);

        c.setFitWidth(140);
        c.setFitWidth(100);
        c.setPreserveRatio(true);

        return c;
    }

    @Override
    public void start(Stage primaryStage) {

        // build camera
        camera = new PerspectiveCamera(true);
        camera.setNearClip(CAMERA_NEAR_CLIP);
        camera.setFarClip(CAMERA_FAR_CLIP);
        camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);

        // we display any node (imageview, webview, etc)
        Node node;

        // create a single webview; we only add it once because we don't want to flood youtube
        WebView webView = new WebView();
        webView.getEngine().load(
          "http://www.youtube.com/embed/utUPth77L_o?autoplay=1"
        );
        webView.setPrefSize(100, 70);

        // wall. the degrees depend on the distance, image size, translate start points, etc. so these values were just as they fit
        double ringBeginDeg = -30;
        double ringEndDeg = 38;

        double r = 1300; 
        double yOffset = 80; // offset per image row
        double yOffsetInitial = 120; // initial y offset from "floor"

        int count=0;

        for( double angle1=Math.toRadians(ringBeginDeg); angle1 <Math.toRadians(ringEndDeg); angle1+=0.08)
        {

            double angle2 = Math.PI;

            for( int i=-3; i <= 3; i++)
            {

                double x = r * Math.sin(angle1) * Math.cos(angle2);
                // double y = r * Math.sin(angle1) * Math.sin(angle2);
                double z = r * Math.cos(angle1);

                // add 1 webview, the rest imageviews 
                if( count == 16) {
                    node = webView;
                } else {
                    node = createImageView();
                }

                node.setTranslateX(x);
                node.setTranslateY(yOffset * i - yOffsetInitial);
                node.setTranslateZ(z);

                // rotate towards viewer position
                Rotate rx = new Rotate();
                rx.setAxis(Rotate.Y_AXIS);
                rx.setAngle(Math.toDegrees( -angle1));

                node.getTransforms().addAll(rx);

                root.getChildren().add( node);

                count++;
            }

        }

        Scene scene = new Scene(root, 1600, 900, Color.BLACK);

        primaryStage.setScene( scene);
        primaryStage.show();

        scene.setCamera(camera);
    }

}

You can add whatever node you prefer. I added a youtube webview for testing. It plays, but the video doesn't get loaded, so all you see is static noise (the grey tile in the screenshot). So in theory you could make the nodes all webview with youtube videos, but that would mean flooding youtube. Better use some offline videos.

Here's a screenshot:

I also toyed around with the full 3d example and creating a ring. That's how it looked like (with always the same image) from an outer view:

Having the camera in the center you can nicely scroll the ring.

If someone wants to toy around, here's a quick & dirty gist with the navigable ring. Use left/right/middle mouse buttons for navigation.

And if you'd like to toy around with a full sphere, you may use this:

// full sphere
for (double angle1 = -Math.PI; angle1 <= Math.PI; angle1 += 0.15) {
    for (double angle2 = -Math.PI; angle2 <= Math.PI; angle2 += 0.15) {

        double x = r * Math.sin(angle1) * Math.cos(angle2);
        double y = r * Math.sin(angle1) * Math.sin(angle2);
        double z = r * Math.cos(angle1);

        c = createImageView();

        c.setTranslateX(x);
        c.setTranslateY(y);
        c.setTranslateZ(z);

        Rotate rx = new Rotate();
        rx.setAxis(Rotate.Y_AXIS);
        rx.setAngle(Math.toDegrees(-angle1));

        c.getTransforms().addAll(rx);

        world.getChildren().add(c);
    }
}

Which looks like this:

But as mentioned, I haven't figured out yet how to rotate all tiles so that they look into the center. And they'd need to be equally distributed. But that's just for fun and off-topic.


Since it's part of the video in my question, it was only a matter of keeping a list of parallel transitions to create the "build-up" animation of the tiles. The bottom row has a reflection now.

The extended code:

public class VideoWall extends Application {

    Random rand = new Random();

    Group root = new Group();
    PerspectiveCamera camera;

    private static final double CAMERA_INITIAL_DISTANCE = -850;
    private static final double CAMERA_NEAR_CLIP = 0.1;
    private static final double CAMERA_FAR_CLIP = 10000.0;

    Image[] images = new Image[] {
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg"),
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/White_Lion.jpg/320px-White_Lion.jpg"),
            new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Lion_female.jpg/319px-Lion_female.jpg")

    };

    List<ParallelTransition> transitionList = new ArrayList<>();

    public VideoWall(){

    }
    public static void main(String[] args) {
        launch(args);
    }

    /**
     * Create ImageView with random Image.
     * @return
     */
    private ImageView createImageView() {

        Image image = images[ rand.nextInt(images.length)];

        ImageView c = new ImageView( image);

        c.setFitWidth(140);
        c.setFitWidth(100);
        c.setPreserveRatio(true);

        return c;
    }

    @Override
    public void start(Stage primaryStage) {

        // build camera
        camera = new PerspectiveCamera(true);
        camera.setNearClip(CAMERA_NEAR_CLIP);
        camera.setFarClip(CAMERA_FAR_CLIP);
        camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);

        // we display any node (imageview, webview, etc)
        Node node;

        // wall. the degrees depend on the distance, image size, translate start points, etc. so these values were just as they fit
        double ringBeginDeg = -30;
        double ringEndDeg = 38;

        double r = 1300; 
        double yOffset = 80; // offset per image row
        double yOffsetInitial = 120; // initial y offset from "floor"

        int min = -3;
        int max = 3;

        for( double angle1=Math.toRadians(ringBeginDeg); angle1 <Math.toRadians(ringEndDeg); angle1+=0.08)
        {

            double angle2 = Math.PI;

            for( int i=min; i <= max; i++)
            {

                double x = r * Math.sin(angle1) * Math.cos(angle2);
                // double y = r * Math.sin(angle1) * Math.sin(angle2);
                double z = r * Math.cos(angle1);

                node = createImageView();

                node.setTranslateX(x);
                node.setTranslateY(yOffset * i - yOffsetInitial);
                node.setTranslateZ(z);

                // rotate towards viewer position
                Rotate rx = new Rotate();
                rx.setAxis(Rotate.Y_AXIS);
                rx.setAngle(Math.toDegrees( -angle1));

                node.getTransforms().addAll(rx);

                // reflection on bottom row
                if( i==max) {
                    Reflection refl = new Reflection();
                    refl.setFraction(0.8f);
                    node.setEffect(refl);
                }

                // build the wall using a transition 
                node.setVisible(false);
                transitionList.add( createTransition( node));

                root.getChildren().add( node);

            }

        }

        Scene scene = new Scene(root, 1600, 900, Color.BLACK);

        primaryStage.setScene( scene);
        primaryStage.show();

        scene.setCamera(camera);

        AnimationTimer timer = createAnimation();
        timer.start();

    }

    private AnimationTimer createAnimation() {

        Collections.sort(transitionList, new Comparator<ParallelTransition>() {

            @Override
            public int compare(ParallelTransition arg0, ParallelTransition arg1) {

                // bottom right to top left
                Point2D ref = new Point2D(1000,1000);
                Point2D pt0 = new Point2D( arg0.getNode().getTranslateX(), arg0.getNode().getTranslateY());
                Point2D pt1 = new Point2D( arg1.getNode().getTranslateX(), arg1.getNode().getTranslateY());

                return Double.compare(ref.distance(pt0), ref.distance(pt1));

                // bottom row first
                // return -Double.compare( arg0.getNode().getTranslateY(), arg1.getNode().getTranslateY());

            }

        });


        AnimationTimer timer = new AnimationTimer() {

            long last = 0;

            @Override
            public void handle(long now) {

                //if( (now - last) > 1_000_000_000) 
                if( (now - last) >   40_000_000) 
                {
                    if( transitionList.size() > 0) {

                        ParallelTransition t = transitionList.remove(0);
                        t.getNode().setVisible(true);
                        t.play();

                    }
                    last = now;

                }

                if( transitionList.size() == 0) {
                    stop();
                }
            }

        };

        return timer;
    }

    private ParallelTransition createTransition( final Node node) {

        Path path = new Path();
        path.getElements().add(new MoveToAbs( node, node.getTranslateX() - 1000, node.getTranslateY() - 900));
        path.getElements().add(new LineToAbs( node, node.getTranslateX(), node.getTranslateY()));

        Duration duration = Duration.millis(1500);

        PathTransition pt = new PathTransition( duration, path, node);

        RotateTransition rt = new RotateTransition( duration, node);
        rt.setByAngle(720);
        rt.setAutoReverse(true);

        ParallelTransition parallelTransition = new ParallelTransition();
        parallelTransition.setNode(node);
        parallelTransition.getChildren().addAll(pt, rt);

        return parallelTransition;

    }

    public static class MoveToAbs extends MoveTo {

        public MoveToAbs( Node node, double x, double y) {
            super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
        }

    }

    public static class LineToAbs extends LineTo {

        public LineToAbs( Node node, double x, double y) {
            super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
        }

    }   

}

这篇关于如何在JavaFX 2.0演示中创建视频墙?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆