From 8530b602948028acd57987e8a3f893932d1b243d Mon Sep 17 00:00:00 2001 From: Stephen Gold Date: Thu, 6 Jul 2017 22:01:57 -0700 Subject: [PATCH] testcases and fix for issue #357 --- .../main/java/com/jme3/renderer/Camera.java | 22 ++-- .../jme3test/renderer/TestAspectRatio.java | 68 +++++++++++ .../jme3test/renderer/TestSplitScreen.java | 115 ++++++++++++++++++ 3 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 jme3-examples/src/main/java/jme3test/renderer/TestAspectRatio.java create mode 100644 jme3-examples/src/main/java/jme3test/renderer/TestSplitScreen.java diff --git a/jme3-core/src/main/java/com/jme3/renderer/Camera.java b/jme3-core/src/main/java/com/jme3/renderer/Camera.java index a51ae0687..a684d360d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Camera.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Camera.java @@ -440,23 +440,25 @@ public class Camera implements Savable, Cloneable { } /** - * Resizes this camera's view with the given width and height. This is - * similar to constructing a new camera, but reusing the same Object. This - * method is called by an associated {@link RenderManager} to notify the camera of - * changes in the display dimensions. + * Resize this camera's view for the specified display size. Invoked by an + * associated {@link RenderManager} to notify the camera of changes to the + * display dimensions. * - * @param width the view width - * @param height the view height - * @param fixAspect If true, the camera's aspect ratio will be recomputed. - * Recomputing the aspect ratio requires changing the frustum values. + * @param width the new width of the display, in pixels + * @param height the new height of the display, in pixels + * @param fixAspect if true, recompute the camera's frustum to preserve its + * prior aspect ratio */ public void resize(int width, int height, boolean fixAspect) { this.width = width; this.height = height; onViewPortChange(); - if (fixAspect /*&& !parallelProjection*/) { - frustumRight = frustumTop * ((float) width / height); + if (fixAspect) { + float h = height * (viewPortTop - viewPortBottom); + float w = width * (viewPortRight - viewPortLeft); + float aspectRatio = w / h; + frustumRight = frustumTop * aspectRatio; frustumLeft = -frustumRight; onFrustumChange(); } diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestAspectRatio.java b/jme3-examples/src/main/java/jme3test/renderer/TestAspectRatio.java new file mode 100644 index 000000000..c557b7f5f --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/renderer/TestAspectRatio.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009-2017 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package jme3test.renderer; + +import com.jme3.app.SimpleApplication; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Box; + +/** + * Simple application to an test a viewport/camera with a different aspect ratio + * than the display -- issue #357. The cube should render as a blue square, not + * a rectangle. + * + * Based closely on the test case submitted by slyh on September 28, 2015. + */ +public class TestAspectRatio extends SimpleApplication { + + public static void main(String[] args) { + new TestAspectRatio().start(); + } + + @Override + public void simpleInitApp() { + Geometry cube = new Geometry("blue cube", new Box(1, 1, 1)); + Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + mat.setColor("Color", ColorRGBA.Blue); + cube.setMaterial(mat); + + rootNode.attachChild(cube); + + // Trying to update the viewport: + cam.setViewPortBottom(0.5f); + cam.resize(640, 480 / 2, false); + cam.setFrustumPerspective(40, 640f / (480 / 2), 0.05f, 500f); + cam.update(); + } +} diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestSplitScreen.java b/jme3-examples/src/main/java/jme3test/renderer/TestSplitScreen.java new file mode 100644 index 000000000..fe6390aaa --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/renderer/TestSplitScreen.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009-2017 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package jme3test.renderer; + +import com.jme3.app.SimpleApplication; +import com.jme3.input.MouseInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.MouseButtonTrigger; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.renderer.Camera; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.shape.Box; + +/** + * Simple application to test split-screen rendering. Clicking with LMB toggles + * between a single camera/viewport (cam) and split screen (leftCam plus + * rightCam). See issue #357. + */ +public class TestSplitScreen extends SimpleApplication implements ActionListener { + + boolean splitScreen = false; + Box mesh = new Box(1f, 1f, 1f); + Camera leftCam, rightCam; + Node leftScene = new Node("left scene"); + ViewPort leftView, rightView; + + @Override + public void simpleInitApp() { + flyCam.setEnabled(false); + + Geometry blueBox = new Geometry("blue box", mesh); + Material blueMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + blueMat.setColor("Color", ColorRGBA.Blue); + blueBox.setMaterial(blueMat); + rootNode.attachChild(blueBox); + + rightCam = cam.clone(); + rightCam.setViewPort(0.5f, 1f, 0f, 1f); + + rightView = renderManager.createMainView("right", rightCam); + rightView.setClearFlags(true, true, true); + rightView.setEnabled(false); + rightView.attachScene(rootNode); + + Geometry redBox = new Geometry("red box", mesh); + Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + redMat.setColor("Color", ColorRGBA.Red); + redBox.setMaterial(redMat); + leftScene.attachChild(redBox); + + leftCam = cam.clone(); + leftCam.setViewPort(0f, 0.5f, 0f, 1f); + + leftView = renderManager.createMainView("left", leftCam); + leftView.setClearFlags(true, true, true); + leftView.setEnabled(false); + leftView.attachScene(leftScene); + + inputManager.addMapping("lmb", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); + inputManager.addListener(this, "lmb"); + } + + @Override + public void onAction(String name, boolean keyPressed, float tpf) { + if (name.equals("lmb") && !keyPressed) { + splitScreen = !splitScreen; + viewPort.setEnabled(!splitScreen); + leftView.setEnabled(splitScreen); + rightView.setEnabled(splitScreen); + } + } + + @Override + public void simpleUpdate(float tpf) { + leftScene.updateLogicalState(tpf); + leftScene.updateGeometricState(); + } + + public static void main(String[] args) { + TestSplitScreen app = new TestSplitScreen(); + app.start(); + } +}