| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <title>Multiple Camera Views :: jMonkeyEngine Docs</title>
- <link rel="canonical" href="https://wiki.jmonkeyengine.org/docs/jme3/advanced/multiple_camera_views.html">
- <meta name="keywords" content="camera, documentation">
- <meta name="generator" content="Antora 2.3.3">
- <link rel="stylesheet" href="../../../_/css/site.css">
- <meta property="og:image" content="https://wiki.jmonkeyengine.org/_/img/iconx128.png">
- <meta property="og:description" content="Multiple Camera Views">
- <meta property="og:title" content="jMonkeyEngine Docs">
- <link rel="stylesheet" href="../../../_/css/site-extra.css">
- <link rel="stylesheet" href="../../../_/css/vendor/docsearch.min.css">
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css -->
- <link rel="icon" href="../../../_/img/favicon.ico" type="image/x-icon">
- </head>
- <body class="article">
- <header class="header">
- <nav class="navbar">
- <div class="navbar-brand">
- <a class="navbar-item" href="https://wiki.jmonkeyengine.org">
- <img alt="" src="../../../_/img/jme-logo.png" height="32" type="image/x-icon">
- </a>
- <div class="navbar-item hide-for-print">
- <input id="search-input" type="text" placeholder="Search docs">
- </div>
- <button class="navbar-burger" data-target="topbar-nav">
- <span></span>
- <span></span>
- <span></span>
- </button>
- </div>
- <div id="topbar-nav" class="navbar-menu">
- <div class="navbar-end">
- <div class="navbar-item theme-switch-wrapper">
- <label class="theme-switch" for="checkbox">
- <input type="checkbox" id="checkbox" />
- <div class="slider round"></div>
- </label>
- </div>
- <a class="navbar-item" href="https://github.com/jmonkeyengine/wiki">Github</a>
- </div>
- </div>
- </nav>
- </header>
- <div class="body">
- <div class="nav-container" data-component="docs" data-version="master">
- <aside class="nav">
- <div class="panels">
- <div class="nav-panel-menu is-active" data-panel="menu">
- <nav class="nav-menu">
- <h3 class="title"><a href="../../documentation.html">Docs</a></h3>
- <ul class="nav-list">
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../documentation.html">Getting Started</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="https://javadoc.jmonkeyengine.org/v3.3.2-stable">JavaDoc</a>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../jme3.html">jMonkeyEngine 3</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Beginner Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_simpleapplication.html">Hello SimpleApplication</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_node.html">Hello Node</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_asset.html">Hello Asset</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_main_event_loop.html">Hello Main Event Loop</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_input_system.html">Hello Input System</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_material.html">Hello Material</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_animation.html">Hello Animation</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_picking.html">Hello Picking</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_collision.html">Hello Collision</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_terrain.html">Hello Terrain</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_audio.html">Hello Audio</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_effects.html">Hello Effects</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_physics.html">Hello Physics</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Intermediate Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/best_practices.html">Best Practices</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/simpleapplication.html">Simple Application</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../features.html">Features</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/optimization.html">Optimization</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../faq.html">FAQ</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Math Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math_for_dummies.html">Math For Dummies</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/math.html">Math</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math.html">More Math</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../rotate.html">Rotate</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math_video_tutorials.html">Math Video Tutorials</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">3D Graphics Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/multi-media_asset_pipeline.html">Multi-Media Asset Pipeline</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../scenegraph_for_dummies.html">Scenegraph for Dummies</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../beginner/hellovector.html">Hello Vector</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../terminology.html">Terminology</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/how_to_use_materials.html">How to Use Materials</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/transparency_sorting.html">Transparency and Sorting</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../external/blender.html">Importing from Blender</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../external/3dsmax.html">Importing from 3DS Max</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../logo.html">Logo Usage</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../bsd_license.html">License</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../github_tips.html">Github Tips</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">SDK</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../sdk.html">jMonkeyEngine SDK</a>
- </li>
- </ul>
- </li>
- </ul>
- </nav>
- </div>
- <div class="nav-panel-explore" data-panel="explore">
- <div class="context">
- <span class="title">Docs</span>
- <span class="version">master</span>
- </div>
- <ul class="components">
- <li class="component is-current">
- <span class="title">Docs</span>
- <ul class="versions">
- <li class="version is-current is-latest">
- <a href="../../documentation.html">master</a>
- </li>
- </ul>
- </li>
- <li class="component">
- <span class="title">Wiki UI</span>
- <ul class="versions">
- <li class="version is-latest">
- <a href="../../../wiki-ui/index.html">master</a>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- </aside>
- </div>
- <main class="article">
- <div class="toolbar" role="navigation">
- <button class="nav-toggle"></button>
- <nav class="breadcrumbs" aria-label="breadcrumbs">
- <ul>
- <li><a href="../../documentation.html">Docs</a></li>
- <li><a href="multiple_camera_views.html">Multiple Camera Views</a></li>
- </ul>
- </nav>
- <div class="edit-this-page"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/docs/modules/ROOT/pages/jme3/advanced/multiple_camera_views.adoc">Edit this Page</a></div>
- </div>
- <div class="content">
- <article class="doc">
- <h1 class="page">Multiple Camera Views</h1>
- <div id="preamble">
- <div class="sectionbody">
- <div class="paragraph">
- <p>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.</p>
- </div>
- <div class="paragraph">
- <p>The packages used in this example are <code>com.jme3.renderer.Camera</code> and <code>com.jme3.renderer.ViewPort</code>. You can get the full sample code here: <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/renderer/TestMultiViews.java">TestMultiViews.java</a></p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="how-to-resize-and-position-viewports"><a class="anchor" href="#how-to-resize-and-position-viewports"></a>How to resize and Position ViewPorts</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>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?</p>
- </div>
- <div class="paragraph">
- <p>Imagine the window as a 1.0f x 1.0f rectangle. The default cam’s viewPort is set to</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">cam.setViewPort(0f, 1f, 0f, 1f);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This setting makes the ViewPort take up the whole rectangle.</p>
- </div>
- <div class="paragraph">
- <p>The four values are read in the following order:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">cam.setViewPort(x1,x2 , y1,y2);</code></pre>
- </div>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p><strong>X-axis</strong> from left to right</p>
- </li>
- <li>
- <p><strong>Y-axis</strong> upwards from bottom to top</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Here are a few examples:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">cam1.setViewPort( 0.0f , 1.0f , 0.0f , 1.0f );
- cam2.setViewPort( 0.5f , 1.0f , 0.0f , 0.5f );</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>These viewport parameters are, (in this order) the left-right extend, and the bottom-top extend of a views’s rectangle on the screen.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code>0.0 , 1.0 1.0 , 1.0
- +-----+-----+
- |cam1 |
- | |
- | +-----+
- | | |
- | |cam2 |
- +-----+-----+
- 0.0 , 0.0 1.0 , 0.0</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>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)</p>
- </div>
- <div class="admonitionblock important">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-important" title="Important"></i>
- </td>
- <td class="content">
- <div class="paragraph">
- <p>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: <code>Camera cam5 = new Camera(100,100);</code></p>
- </div>
- </td>
- </tr>
- </table>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="four-time-split-screen"><a class="anchor" href="#four-time-split-screen"></a>Four-Time Split Screen</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>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.</p>
- </div>
- <div class="sect2">
- <h3 id="set-up-the-first-view"><a class="anchor" href="#set-up-the-first-view"></a>Set up the First View</h3>
- <div class="paragraph">
- <p>You use the preconfigured Camera <code>cam</code> and <code>viewPort</code> from <code>SimpleApplication</code> for the first view. It’s in the bottom right.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">cam.setViewPort(.5f, 1f, 0f, 0.5f); // Resize the viewPort to half its size, bottom right.</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Optionally, place the main camera in the scene and rotate it in its start position.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">cam.setLocation(new Vector3f(3.32f, 4.48f, 4.28f));
- cam.setRotation(new Quaternion (-0.07f, 0.92f, -0.25f, -0.27f));</code></pre>
- </div>
- </div>
- </div>
- <div class="sect2">
- <h3 id="set-up-three-more-views"><a class="anchor" href="#set-up-three-more-views"></a>Set Up Three More Views</h3>
- <div class="paragraph">
- <p>Here is the outline for how you create the three other cams and viewPorts (<a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/renderer/TestMultiViews.java">Full code sample is here</a>.) In the code snippet, <code>cam_n</code> stand for <code>cam_2</code> - <code>cam_4</code>, respectively, same for <code>view_n</code>.</p>
- </div>
- <div class="olist arabic">
- <ol class="arabic">
- <li>
- <p>Clone the first cam to reuse its settings</p>
- </li>
- <li>
- <p>Resize and position the cam’s viewPort with setViewPort().</p>
- </li>
- <li>
- <p>(Optionally) Move the cameras in the scene and rotate them so they face what you want to see.</p>
- </li>
- <li>
- <p>Create a ViewPort for each camera</p>
- </li>
- <li>
- <p>Reset the camera’s enabled statuses</p>
- </li>
- <li>
- <p>Attach the Node to be displayed to this ViewPort.<br>
- The camera doesn’t have to look at the rootNode, but that is the most common use case.</p>
- </li>
- </ol>
- </div>
- <div class="paragraph">
- <p>Here is the abstract code sample for camera <code>n</code>:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="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);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>To visualize what you do, use the following drawing of the viewport positions:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code>0.0 , 1.0 1.0 , 1.0
- +-----+-----+
- | | |
- |cam3 |cam4 |
- +-----------+
- | | |
- |cam2 |cam1 |
- +-----+-----+
- 0.0 , 0.0 1.0 , 0.0</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This are the lines of code that set the four cameras to create a four-times split screen.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="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);</code></pre>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="picture-in-picture"><a class="anchor" href="#picture-in-picture"></a>Picture in Picture</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>The following code snippet sets up two views, one covers the whole screen, and the second is a small view in the top center.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code> +-----+-----+
- | |cam| |
- | | 2 | |
- + +---+ +
- | |
- | cam |
- +-----+-----+</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="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);</code></pre>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="viewport-settings"><a class="anchor" href="#viewport-settings"></a>ViewPort Settings</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>You can customize the camera and the viewPort of each view individually. For example, each view can have a different background color:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">viewPort.setBackgroundColor(ColorRGBA.Blue);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>You have full control to determine which Nodes the camera can see! It can see the full rootNode…</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">viewPort1.attachScene(rootNode);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>… or you can give each camera a special node whose content it can see:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">viewPort2.attachScene(spookyGhostDetectorNode);</code></pre>
- </div>
- </div>
- </div>
- </div>
- </article>
- <aside class="toc sidebar" data-title="Contents" data-levels="2">
- <div class="toc-menu"></div>
- </aside>
- </div>
- </main>
- </div>
- <footer class="footer">
- <p>Copyright 2020 jMonkeyEngine Wiki Contributors. Licensed BSD-3.</p>
- </footer>
- <script src="../../../_/js/vendor/docsearch.min.js"></script>
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js -->
- <script>
- var search = docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#search-input',
- autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
- algoliaOptions: { hitsPerPage: 10 }
- }).autocomplete
- search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
- function focusSearchInput () { document.querySelector('#search-input').focus() }
- if (document.querySelector('.home-link.is-current')) window.addEventListener('load', focusSearchInput)
- </script>
- <script src="../../../_/js/site.js"></script>
- <script async src="../../../_/js/vendor/highlight.js"></script>
- </body>
- </html>
|