我是JavaFX和Java的新手。我想知道如何在立方體或任何多面體的表面上製作場景?我想在任何3D形狀的表面上播放視頻。我怎麼能這樣做呢?如何使用JavaFX在3D形狀上播放視頻?
5
A
回答
5
這裏是使用了內置的JavaFX的MediaPlayer並採取在介質上的圖的定期快照到紋理圖像映射到3D形狀(在這種情況下的樣品一個盒子)。添加Y軸周圍的旋轉動畫,以便可以以透視的方式查看框的兩側。
import javafx.animation.*;
import javafx.application.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.*;
import javafx.scene.image.WritableImage;
import javafx.scene.media.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
// Display a rotating 3D box with a video projected onto its surface.
public class ThreeDMedia extends Application {
private static final String MEDIA_URL =
"http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv";
private static final int SCENE_W = 640;
private static final int SCENE_H = 400;
private static final double MEDIA_W = 540 * 2/3;
private static final double MEDIA_H = 209 * 2/3;
private static final Color INDIA_INK = Color.rgb(35, 39, 50);
@Override
public void start(Stage stage) {
// create a 3D box shape on which to project the video.
Box box = new Box(MEDIA_W, MEDIA_H, MEDIA_W);
box.setTranslateX(SCENE_W/2);
box.setTranslateY(SCENE_H/2);
// create a media player for the video which loops the video forever.
MediaPlayer player = new MediaPlayer(new Media(MEDIA_URL));
player.setCycleCount(MediaPlayer.INDEFINITE);
// create a media view for the video, sized to our specifications.
MediaView mediaView = new MediaView(player);
mediaView.setPreserveRatio(false);
mediaView.setFitWidth(MEDIA_W);
mediaView.setFitHeight(MEDIA_H);
// project the video on to the 3D box.
showMediaOnShape3D(box, mediaView);
// rotate the box.
rotateAroundYAxis(box);
// create a point light source a fair way away so lighting is reasonably even.
PointLight pointLight = new PointLight(
Color.WHITE
);
pointLight.setTranslateX(SCENE_W/2);
pointLight.setTranslateY(SCENE_H/2);
pointLight.setTranslateZ(-SCENE_W * 5);
// add a bit of ambient light to make the lighting more natural.
AmbientLight ambientLight = new AmbientLight(
Color.rgb(15, 15, 15)
);
// place the shape and associated lights in a group.
Group group = new Group(
box,
pointLight,
ambientLight
);
// create a 3D scene with a default perspective camera.
Scene scene = new Scene(
group,
SCENE_W, SCENE_H, true, SceneAntialiasing.BALANCED
);
scene.setFill(INDIA_INK);
PerspectiveCamera camera = new PerspectiveCamera();
scene.setCamera(camera);
stage.setScene(scene);
stage.setResizable(false);
// start playing the media, showing the scene once the media is ready to play.
player.setOnReady(stage::show);
player.setOnError(Platform::exit);
player.play();
}
// Project video on to 3D shape.
private void showMediaOnShape3D(Shape3D shape3D, final MediaView mediaView) {
PhongMaterial material = new PhongMaterial();
shape3D.setMaterial(material);
Scene mediaScene = new Scene(
new Group(mediaView),
MEDIA_W, MEDIA_H
);
SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setViewport(
new Rectangle2D(
0, 0, MEDIA_W, MEDIA_H
)
);
WritableImage textureImage = mediaView.snapshot(
snapshotParameters,
null
);
material.setDiffuseMap(textureImage);
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
mediaView.snapshot(
snapshotParameters,
textureImage
);
}
};
timer.start();
}
// Rotates a shape around the y axis indefinitely.
private void rotateAroundYAxis(Shape3D shape3D) {
RotateTransition rotateY = new RotateTransition(
Duration.seconds(10),
shape3D
);
rotateY.setAxis(Rotate.Y_AXIS);
rotateY.setFromAngle(360);
rotateY.setToAngle(0);
rotateY.setCycleCount(RotateTransition.INDEFINITE);
rotateY.setInterpolator(Interpolator.LINEAR);
rotateY.play();
}
public static void main(String[] args) {
launch(args);
}
}
5
其實,你可以在任何3D形狀上播放視頻。
有一個優秀的@caprica視頻播放項目VLCJ:VLC媒體播放器的Java框架。
雖然該項目旨在用AWT畫布呈現,但作者已完成一些tests以在JavaFX Canvas
中呈現該項目。
根據他的JavaFX類,很容易呈現在三維形狀而不是2D畫布結點的緩衝器。
設置
首先,您需要安裝第一VLC視頻播放器。
然後你需要一些依賴關係:vlcj-3.6.0.jar,jna-3.5-2.jar & platform-3.5.2.jar和slfj4j-api.1.7.12.jar。
另外,我將使用FXyz庫中的一些自定義3D形狀,但您可以使用API中的常規3D形狀,例如Box
。
基礎
上呈現3D形狀視頻正在利用其材料,其拍攝圖像,並且限定其質地的漫地圖訣竅。
所以可用的每一幀,我們將創建一個新的形象,並將其設置爲漫反射貼圖:
ByteBuffer byteBuffer = nativeBuffer.getByteBuffer(0, nativeBuffer.size());
BufferFormat bufferFormat = ((DefaultDirectMediaPlayer) mediaPlayerComponent.getMediaPlayer()).getBufferFormat();
WritableImage textureImage = new WritableImage(bufferFormat.getWidth(), bufferFormat.getHeight());
if (bufferFormat.getWidth() > 0 && bufferFormat.getHeight() > 0) {
textureImage.getPixelWriter().setPixels(0, 0, bufferFormat.getWidth(), bufferFormat.getHeight(), pixelFormat, byteBuffer, bufferFormat.getPitches()[0]);
// apply new frame as texture image to the 3D shape's material
material.setDiffuseMap(textureImage);
}
的AnimationTimer
將允許更新框架和質感。
樣品
這是呈現在分段環形視頻工作示例。
public class Video3D extends Application {
static {
// path to the VLC video player
System.setProperty("jna.library.path", "C:/Program Files/VideoLAN/VLC");
}
// http://download.blender.org/peach/bigbuckbunny_movies/
// (c) copyright 2008, Blender Foundation/www.bigbuckbunny.org
private static final String VIDEO_FILE = "C:\\BigBuckBunny_320x180.mp4";
private final DirectMediaPlayerComponent mediaPlayerComponent;
private final WritablePixelFormat<ByteBuffer> pixelFormat;
private final SegmentedTorusMesh torus = new SegmentedTorusMesh(50,40,12,3.2d,4.5d);
private final PhongMaterial material = new PhongMaterial(Color.WHEAT);
private double mousePosX, mousePosY;
private double mouseOldX, mouseOldY;
private final Rotate rotateX = new Rotate(-20, Rotate.X_AXIS);
private final Rotate rotateY = new Rotate(240, Rotate.Y_AXIS);
private final AnimationTimer timer;
public TestVLC(){
mediaPlayerComponent = new TestMediaPlayerComponent();
pixelFormat = PixelFormat.getByteBgraInstance();
timer = new AnimationTimer() {
@Override
public void handle(long now) {
renderFrame();
}
};
}
protected void startTimer() {
mediaPlayerComponent.getMediaPlayer().playMedia(VIDEO_FILE);
timer.start();
}
protected void stopTimer() {
mediaPlayerComponent.getMediaPlayer().stop();
timer.stop();
}
@Override
public void start(Stage primaryStage) {
torus.setCullFace(CullFace.NONE);
torus.setzOffset(1.4);
torus.setMaterial(material);
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.getTransforms().addAll (rotateX, rotateY, new Translate(0, 0, -30));
Group root3D = new Group(camera,torus);
SubScene subScene = new SubScene(root3D, 800, 600, true, SceneAntialiasing.BALANCED);
subScene.setFill(Color.AQUAMARINE);
subScene.setCamera(camera);
BorderPane pane = new BorderPane();
pane.setCenter(subScene);
Button play = new Button("Play");
play.setOnAction(e->startTimer());
Button stop = new Button("Stop");
stop.setOnAction(e->stopTimer());
ToolBar toolBar = new ToolBar(play, stop);
toolBar.setOrientation(Orientation.VERTICAL);
pane.setRight(toolBar);
pane.setPrefSize(600,400);
Scene scene = new Scene(pane);
scene.setOnMousePressed((MouseEvent me) -> {
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
});
scene.setOnMouseDragged((MouseEvent me) -> {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
rotateX.setAngle(rotateX.getAngle()-(mousePosY - mouseOldY));
rotateY.setAngle(rotateY.getAngle()+(mousePosX - mouseOldX));
mouseOldX = mousePosX;
mouseOldY = mousePosY;
});
primaryStage.setScene(scene);
primaryStage.setTitle("Video - JavaFX 3D");
primaryStage.show();
}
@Override
public final void stop() throws Exception {
stopTimer();
mediaPlayerComponent.getMediaPlayer().stop();
mediaPlayerComponent.getMediaPlayer().release();
}
/**
* Implementation of a direct rendering media player component that renders
* the video to a JavaFX canvas.
* https://github.com/caprica/vlcj-javafx/blob/master/src/test/java/uk/co/caprica/vlcj/javafx/test/JavaFXDirectRenderingTest.java
*/
private class TestMediaPlayerComponent extends DirectMediaPlayerComponent {
public TestMediaPlayerComponent() {
super(new TestBufferFormatCallback());
}
}
/**
* Callback to get the buffer format to use for video playback.
*/
private class TestBufferFormatCallback implements BufferFormatCallback {
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
final int width = sourceWidth;
final int height = sourceHeight;
Platform.runLater(() -> {
torus.setMajorRadius(width/100);
torus.setMinorRadius(height/40);
});
return new RV32BufferFormat(width, height);
}
}
protected final void renderFrame() {
Memory[] nativeBuffers = mediaPlayerComponent.getMediaPlayer().lock();
if (nativeBuffers != null) {
Memory nativeBuffer = nativeBuffers[0];
if (nativeBuffer != null) {
ByteBuffer byteBuffer = nativeBuffer.getByteBuffer(0, nativeBuffer.size());
BufferFormat bufferFormat = ((DefaultDirectMediaPlayer) mediaPlayerComponent.getMediaPlayer()).getBufferFormat();
WritableImage textureImage = new WritableImage(bufferFormat.getWidth(), bufferFormat.getHeight());
if (bufferFormat.getWidth() > 0 && bufferFormat.getHeight() > 0) {
textureImage.getPixelWriter().setPixels(0, 0, bufferFormat.getWidth(), bufferFormat.getHeight(), pixelFormat, byteBuffer, bufferFormat.getPitches()[0]);
material.setDiffuseMap(textureImage);
}
}
}
mediaPlayerComponent.getMediaPlayer().unlock();
}
public static void main(String[] args) {
launch(args);
}
}
而這些只是你將得到的兩個快照。
2
除了jewelsea的和何塞的更優雅的解決方案,你總是可以手動在三維空間e放置一個MediaView。 G。作爲6個面的立方體:
public class VideoCubeDemo extends Application {
Random rnd = new Random();
// size of the cube
double size = 320;
@Override
public void start(Stage primaryStage) throws MalformedURLException {
// create media views
List<String> videoFiles = new ArrayList<>();
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
videoFiles.add(getClass().getResource("funny_cats_compilation_2012.mp4").toExternalForm());
// create faces for the cube
// original cube face code from http://www.javafxapps.in/tutorial/Creating-3D-Cube-in-javafx.html
MediaView r;
int videoIndex;
Group cube = new Group();
List<MediaView> cubeFaces = new ArrayList<>();
// back face
videoIndex = 0;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-0.5 * size);
r.setTranslateZ(0.5 * size);
cubeFaces.add(r);
// bottom face
videoIndex = 1;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(-0.5 * size);
r.setTranslateY(0);
r.setRotationAxis(Rotate.X_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// right face
videoIndex = 2;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(-1 * size);
r.setTranslateY(-0.5 * size);
r.setRotationAxis(Rotate.Y_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// left face
videoIndex = 3;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(0);
r.setTranslateY(-0.5 * size);
r.setRotationAxis(Rotate.Y_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// top face
videoIndex = 4;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-1 * size);
r.setRotationAxis(Rotate.X_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// front face
videoIndex = 5;
r = createMediaView(videoFiles.get(videoIndex));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-0.5 * size);
r.setTranslateZ(-0.5 * size);
cubeFaces.add(r);
// create cube with all faces
cube.getChildren().addAll(cubeFaces);
// initial cube rotation
cube.getTransforms().addAll(new Rotate(45, Rotate.X_AXIS), new Rotate(45, Rotate.Y_AXIS));
// animate cube
Point3D rotateAxis = new Point3D(1,1,1); // rotate around X, Y and Z
Timeline animation = new Timeline();
animation.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO, new KeyValue(cube.rotationAxisProperty(), rotateAxis), new KeyValue(cube.rotateProperty(), 0d)),
new KeyFrame(Duration.seconds(5), new KeyValue(cube.rotationAxisProperty(), rotateAxis), new KeyValue(cube.rotateProperty(), 360d))
);
animation.setCycleCount(Animation.INDEFINITE);
// add objects to scene
StackPane root = new StackPane();
root.getChildren().add(cube);
Scene scene = new Scene(root, 1600, 900, true, SceneAntialiasing.BALANCED);
scene.setFill(Color.BLACK);
scene.setCamera(new PerspectiveCamera());
primaryStage.setResizable(true);
primaryStage.setScene(scene);
primaryStage.show();
// play videos and animation
for(MediaView mediaPlayer: cubeFaces) {
mediaPlayer.getMediaPlayer().play();
}
animation.play();
}
private MediaView createMediaView(String path) {
Media media = new Media(path);
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.setVolume(0.8);
mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
MediaView mediaView = new MediaView(mediaPlayer);
mediaView.setFitHeight(size);
mediaView.setFitWidth(size);
mediaView.setPreserveRatio(false);
return mediaView;
}
public static void main(String[] args) {
launch(args);
}
}
相關問題
- 1. 在Android上播放3D旋轉視頻
- 2. 如何在使用javafx播放視頻時使用時間線
- 3. JMC/JavaFX - 播放視頻
- 4. JavaFX視頻沒有播放
- 5. 播放QuickTime視頻的JavaFX
- 6. javafx視頻播放器timeSlider
- 7. JavaFX - 播放循環視頻
- 8. 如何在linux上的javaFX中播放視頻
- 9. JavaFX的WebEngine視頻播放在Linux中
- 10. 在javafx中播放加密視頻
- 11. 在JavaFX中播放連續視頻
- 12. 在JavaFX中播放Youtube視頻
- 13. 嵌入開放圖形視頻不使用視頻播放器
- 14. 使用OMXPLAYER在QT上播放視頻
- 15. 在Mac上使用vlcj播放視頻
- 16. 在視頻播放中播放視頻
- 17. Javafx 8 3D複雜形狀
- 18. 如何在YouTube上播放器上播放視頻網址(Android)
- 19. 如何在JPanel上播放mp4視頻?
- 20. 如何在videoview上播放.mp4視頻
- 21. 如何在xna4.0上播放視頻(avi)?
- 22. 如何在抽搐上播放視頻?
- 23. 如何在VideoView上播放Youtube視頻?
- 24. 如何在視頻播放器中播放視頻
- 25. 在SurfaceView上播放視頻
- 26. 在TextureView上播放視頻
- 27. 在iPhone上播放視頻
- 28. 在BlackBerry上播放視頻
- 29. 使用ffmpeg在視頻轉換後在iPhone上播放視頻
- 30. JavaFX - 播放視頻作爲背景
這是非常真棒時看到其應用在一個球形或圓柱形,它也適用。感謝分享! – Roland