= Multiple Camera Views
:author:
:revnumber:
:revdate: 2016/03/17 20:48
:keywords: camera, documentation
:relfileprefix: ../../
:imagesdir: ../..
ifdef::env-github,env-browser[:outfilesuffix: .adoc]


You can split the screen and look into the 3D scene from different camera angles at the same time. E.g. you can have two rootnodes with different scene graphs, and two viewPorts, each of which can only see its own subset of the scene with its own subset of port-processing filters, so you get two very different views of the scene.

The packages used in this example are `com.jme3.renderer.Camera` and `com.jme3.renderer.ViewPort`. You can get the full sample code here: link:https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/renderer/TestMultiViews.java[TestMultiViews.java]


== How to resize and Position ViewPorts

The default viewPort is as big as the window. If you have several, they must be of different sizes, either overlapping or adjacent to one another. How do you tell jME which of the ViewPorts should appear where on the screen, and how big they should be?

Imagine the window as a 1.0f x 1.0f rectangle. The default cam's viewPort is set to

[source,java]
----
cam.setViewPort(0f, 1f, 0f, 1f);
----

This setting makes the ViewPort take up the whole rectangle.

The four values are read in the following order:

[source,java]
----
cam.setViewPort(x1,x2 , y1,y2);
----

*  *X-axis* from left to right
*  *Y-axis* upwards from bottom to top

Here are a few examples:

[source,java]
----

cam1.setViewPort( 0.0f , 1.0f   ,   0.0f , 1.0f );
cam2.setViewPort( 0.5f , 1.0f   ,   0.0f , 0.5f );

----

These viewport parameters are, (in this order) the left-right extend, and the bottom-top extend of a views's rectangle on the screen.

[source]
----

0.0 , 1.0       1.0 , 1.0
       +-----+-----+
       |cam1       |
       |           |
       |     +-----+
       |     |     |
       |     |cam2 |
       +-----+-----+
0.0 , 0.0       1.0 , 0.0
----

Example: Cam2's rectangle is in the bottom right: It extends from mid (x1=0.5f) bottom (y1=0.0f), to right (x2=1.0f) mid (y2=0.5f)


[IMPORTANT]
====
If you scale the views in a way so that the aspect ratio of a ViewPort is different than the window's aspect ratio, then the ViewPort appears distorted. In these cases, you must recreate (not clone) the ViewPort's cam object with the right aspect ratio. For example: `Camera cam5 = new Camera(100,100);`
====



== Four-Time Split Screen

In this example, you create four views (2x2) with the same aspect ratio as the window, but each is only half the width and height.


=== Set up the First View

You use the preconfigured Camera `cam` and `viewPort` from `SimpleApplication` for the first view. It's in the bottom right.

[source,java]
----

cam.setViewPort(.5f, 1f, 0f, 0.5f); // Resize the viewPort to half its size, bottom right.

----

Optionally, place the main camera in the scene and rotate it in its start position.

[source,java]
----
cam.setLocation(new Vector3f(3.32f, 4.48f, 4.28f));
cam.setRotation(new Quaternion (-0.07f, 0.92f, -0.25f, -0.27f));

----


=== Set Up Three More Views

Here is the outline for how you create the three other cams and viewPorts (link:https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/renderer/TestMultiViews.java[Full code sample is here].) In the code snippet, `cam_n` stand for `cam_2` - `cam_4`, respectively, same for `view_n`.

.  Clone the first cam to reuse its settings
.  Resize and position the cam's viewPort with setViewPort().
.  (Optionally) Move the cameras in the scene and rotate them so they face what you want to see.
.  Create a ViewPort for each camera
.  Reset the camera's enabled statuses
.  Attach the Node to be displayed to this ViewPort. +
The camera doesn't have to look at the rootNode, but that is the most common use case.

Here is the abstract code sample for camera `n`:

[source,java]
----

Camera cam_n    = cam.clone();
cam_n.setViewPort(...); // resize the viewPort
cam_n.setLocation(new Vector3f(...));
cam_n.setRotation(new Quaternion(...));

ViewPort view_n = renderManager.createMainView("View of camera #n", cam_n);
view_n.setClearEnabled(true);
view_n.attachScene(rootNode);
view_n.setBackgroundColor(ColorRGBA.Black);

----

To visualize what you do, use the following drawing of the viewport positions:

[source]
----

0.0 , 1.0       1.0 , 1.0
       +-----+-----+
       |     |     |
       |cam3 |cam4 |
       +-----------+
       |     |     |
       |cam2 |cam1 |
       +-----+-----+
0.0 , 0.0       1.0 , 0.0
----

This are the lines of code that set the four cameras to create a four-times split screen.

[source,java]
----

cam1.setViewPort( 0.5f , 1.0f  ,  0.0f , 0.5f);
...
cam2.setViewPort( 0.0f , 0.5f  ,  0.0f , 0.5f);
...
cam3.setViewPort( 0.0f , 0.5f  ,  0.5f , 1.0f);
...
cam4.setViewPort( 0.5f , 1.0f  ,  0.5f , 1.0f);

----


== Picture in Picture

The following code snippet sets up two views, one covers the whole screen, and the second is a small view in the top center.

[source]
----

       +-----+-----+
       |   |cam|   |
       |   | 2 |   |
       +   +---+   +
       |           |
       |    cam    |
       +-----+-----+

----

[source,java]
----

// Setup first full-window view
cam.setViewPort(0f, 1f, 0f, 1f);
cam.setLocation(new Vector3f(3.32f, 4.48f, 4.28f));
cam.setRotation(new Quaternion(-0.07f, 0.92f, -0.25f, -0.27f));

// Setup second, smaller PiP view
Camera cam2 = cam.clone();
cam2.setViewPort(.4f, .6f, 0.8f, 1f);
cam2.setLocation(new Vector3f(-0.10f, 1.57f, 4.81f));
cam2.setRotation(new Quaternion(0.00f, 0.99f, -0.04f, 0.02f));
ViewPort viewPort2 = renderManager.createMainView("PiP", cam2);
viewPort2.setClearFlags(true, true, true);
viewPort2.attachScene(rootNode);

----


== ViewPort Settings

You can customize the camera and the viewPort of each view individually. For example, each view can have a different background color:

[source,java]
----
viewPort.setBackgroundColor(ColorRGBA.Blue);
----

You have full control to determine which Nodes the camera can see! It can see the full rootNode…

[source,java]
----
viewPort1.attachScene(rootNode);
----

… or you can give each camera a special node whose content it can see:

[source,java]
----
viewPort2.attachScene(spookyGhostDetectorNode);
----
