Skip to content

Commit 09b862d

Browse files
authored
Merge pull request jMonkeyEngine#2388 from jMonkeyEngine/sgold/issue/2333
solve issue jMonkeyEngine#2333 (Camera viewport dimensions not checked)
2 parents 832814b + fdf1df1 commit 09b862d

File tree

2 files changed

+267
-13
lines changed

2 files changed

+267
-13
lines changed

jme3-core/src/main/java/com/jme3/renderer/Camera.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -179,22 +179,22 @@ public enum FrustumIntersect {
179179
//view port coordinates
180180
/**
181181
* Percent value on display where horizontal viewing starts for this camera.
182-
* Default is 0.
182+
* Default is 0. Must be less than {@code viewPortRight}.
183183
*/
184184
protected float viewPortLeft;
185185
/**
186186
* Percent value on display where horizontal viewing ends for this camera.
187-
* Default is 1.
187+
* Default is 1. Must be greater than {@code viewPortLeft}.
188188
*/
189189
protected float viewPortRight;
190190
/**
191191
* Percent value on display where vertical viewing ends for this camera.
192-
* Default is 1.
192+
* Default is 1. Must be greater than {@code viewPortBottom}.
193193
*/
194194
protected float viewPortTop;
195195
/**
196196
* Percent value on display where vertical viewing begins for this camera.
197-
* Default is 0.
197+
* Default is 0. Must be less than {@code viewPortTop}.
198198
*/
199199
protected float viewPortBottom;
200200
/**
@@ -1017,7 +1017,8 @@ public float getViewPortLeft() {
10171017
/**
10181018
* Sets the left boundary of the viewport.
10191019
*
1020-
* @param left the left boundary of the viewport
1020+
* @param left the left boundary of the viewport (<viewPortRight,
1021+
* default: 0)
10211022
*/
10221023
public void setViewPortLeft(float left) {
10231024
viewPortLeft = left;
@@ -1036,7 +1037,8 @@ public float getViewPortRight() {
10361037
/**
10371038
* Sets the right boundary of the viewport.
10381039
*
1039-
* @param right the right boundary of the viewport
1040+
* @param right the right boundary of the viewport (>viewPortLeft,
1041+
* default: 1)
10401042
*/
10411043
public void setViewPortRight(float right) {
10421044
viewPortRight = right;
@@ -1055,7 +1057,8 @@ public float getViewPortTop() {
10551057
/**
10561058
* Sets the top boundary of the viewport.
10571059
*
1058-
* @param top the top boundary of the viewport
1060+
* @param top the top boundary of the viewport (>viewPortBottom,
1061+
* default: 1)
10591062
*/
10601063
public void setViewPortTop(float top) {
10611064
viewPortTop = top;
@@ -1074,7 +1077,8 @@ public float getViewPortBottom() {
10741077
/**
10751078
* Sets the bottom boundary of the viewport.
10761079
*
1077-
* @param bottom the bottom boundary of the viewport
1080+
* @param bottom the bottom boundary of the viewport (<viewPortTop,
1081+
* default: 0)
10781082
*/
10791083
public void setViewPortBottom(float bottom) {
10801084
viewPortBottom = bottom;
@@ -1084,10 +1088,10 @@ public void setViewPortBottom(float bottom) {
10841088
/**
10851089
* Sets the boundaries of the viewport.
10861090
*
1087-
* @param left the left boundary of the viewport (default: 0)
1088-
* @param right the right boundary of the viewport (default: 1)
1089-
* @param bottom the bottom boundary of the viewport (default: 0)
1090-
* @param top the top boundary of the viewport (default: 1)
1091+
* @param left the left boundary of the viewport (<right, default: 0)
1092+
* @param right the right boundary of the viewport (>left, default: 1)
1093+
* @param bottom the bottom boundary of the viewport (<top, default: 0)
1094+
* @param top the top boundary of the viewport (>bottom, default: 1)
10911095
*/
10921096
public void setViewPort(float left, float right, float bottom, float top) {
10931097
this.viewPortLeft = left;
@@ -1283,6 +1287,15 @@ public void clearViewportChanged() {
12831287
* Called when the viewport has been changed.
12841288
*/
12851289
public void onViewPortChange() {
1290+
if (!(viewPortBottom < viewPortTop)) {
1291+
throw new IllegalArgumentException(
1292+
"Viewport must have bottom < top");
1293+
}
1294+
if (!(viewPortLeft < viewPortRight)) {
1295+
throw new IllegalArgumentException(
1296+
"Viewport must have left < right");
1297+
}
1298+
12861299
viewportChanged = true;
12871300
setGuiBounding();
12881301
}
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/*
2+
* Copyright (c) 2025 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package com.jme3.renderer;
33+
34+
import org.junit.Assert;
35+
import org.junit.Test;
36+
37+
/**
38+
* Automated tests for "Camera Viewport Dimensions not Checked" (issue #2333 at
39+
* GitHub).
40+
*
41+
* @author Stephen Gold sgold@sonic.net
42+
*/
43+
public class Issue2333Test {
44+
45+
/**
46+
* Tests some basic functionality of the viewport settings.
47+
*/
48+
@Test
49+
public void testIssue2333() {
50+
Camera c = new Camera(1, 1);
51+
52+
// Verify some Camera defaults:
53+
Assert.assertEquals(0f, c.getViewPortBottom(), 0f);
54+
Assert.assertEquals(0f, c.getViewPortLeft(), 0f);
55+
Assert.assertEquals(1f, c.getViewPortRight(), 0f);
56+
Assert.assertEquals(1f, c.getViewPortTop(), 0f);
57+
58+
// Try some valid settings:
59+
new Camera(1, 1).setViewPort(0.5f, 0.7f, 0.1f, 0.3f);
60+
new Camera(1, 1).setViewPortBottom(0.9f);
61+
new Camera(1, 1).setViewPortLeft(0.99f);
62+
new Camera(1, 1).setViewPortRight(0.01f);
63+
new Camera(1, 1).setViewPortTop(0.1f);
64+
}
65+
66+
/**
67+
* Verifies that setViewPort() with left = right throws an
68+
* IllegalArgumentException.
69+
*/
70+
@Test(expected = IllegalArgumentException.class)
71+
public void iaeCase01() {
72+
new Camera(1, 1).setViewPort(0.5f, 0.5f, 0f, 1f);
73+
}
74+
75+
/**
76+
* Verifies that setViewPort() with left > right throws an
77+
* IllegalArgumentException.
78+
*/
79+
@Test(expected = IllegalArgumentException.class)
80+
public void iaeCase02() {
81+
new Camera(1, 1).setViewPort(0.7f, 0.5f, 0f, 1f);
82+
}
83+
84+
/**
85+
* Verifies that setViewPortLeft() resulting in left = right throws an
86+
* IllegalArgumentException.
87+
*/
88+
@Test(expected = IllegalArgumentException.class)
89+
public void iaeCase03() {
90+
new Camera(1, 1).setViewPortLeft(1f);
91+
}
92+
93+
/**
94+
* Verifies that setViewPortLeft() resulting in left > right throws an
95+
* IllegalArgumentException.
96+
*/
97+
@Test(expected = IllegalArgumentException.class)
98+
public void iaeCase04() {
99+
new Camera(1, 1).setViewPortLeft(1.1f);
100+
}
101+
102+
/**
103+
* Verifies that setViewPortRight() resulting in left = right throws an
104+
* IllegalArgumentException.
105+
*/
106+
@Test(expected = IllegalArgumentException.class)
107+
public void iaeCase05() {
108+
new Camera(1, 1).setViewPortRight(0f);
109+
}
110+
111+
/**
112+
* Verifies that setViewPortRight() resulting in left > right throws an
113+
* IllegalArgumentException.
114+
*/
115+
@Test(expected = IllegalArgumentException.class)
116+
public void iaeCase06() {
117+
new Camera(1, 1).setViewPortRight(-0.1f);
118+
}
119+
120+
/**
121+
* Verifies that setViewPort() with bottom = top throws an
122+
* IllegalArgumentException.
123+
*/
124+
@Test(expected = IllegalArgumentException.class)
125+
public void iaeCase07() {
126+
new Camera(1, 1).setViewPort(0f, 1f, 0.5f, 0.5f);
127+
}
128+
129+
/**
130+
* Verifies that setViewPort() with bottom > top throws an
131+
* IllegalArgumentException.
132+
*/
133+
@Test(expected = IllegalArgumentException.class)
134+
public void iaeCase08() {
135+
new Camera(1, 1).setViewPort(0f, 1f, 0.7f, 0.6f);
136+
}
137+
138+
/**
139+
* Verifies that setViewPortBottom() resulting in bottom = top throws an
140+
* IllegalArgumentException.
141+
*/
142+
@Test(expected = IllegalArgumentException.class)
143+
public void iaeCase09() {
144+
new Camera(1, 1).setViewPortBottom(1f);
145+
}
146+
147+
/**
148+
* Verifies that setViewPortBottom() resulting in bottom > top throws an
149+
* IllegalArgumentException.
150+
*/
151+
@Test(expected = IllegalArgumentException.class)
152+
public void iaeCase10() {
153+
new Camera(1, 1).setViewPortBottom(2f);
154+
}
155+
156+
/**
157+
* Verifies that setViewPortTop() resulting in bottom = top throws an
158+
* IllegalArgumentException.
159+
*/
160+
@Test(expected = IllegalArgumentException.class)
161+
public void iaeCase11() {
162+
new Camera(1, 1).setViewPortTop(0f);
163+
}
164+
165+
/**
166+
* Verifies that setViewPortTop() resulting in bottom > top throws an
167+
* IllegalArgumentException.
168+
*/
169+
@Test(expected = IllegalArgumentException.class)
170+
public void iaeCase12() {
171+
new Camera(1, 1).setViewPortTop(-1f);
172+
}
173+
174+
/**
175+
* Verifies that setViewPort() with left = NaN throws an
176+
* IllegalArgumentException.
177+
*/
178+
@Test(expected = IllegalArgumentException.class)
179+
public void iaeCase13() {
180+
new Camera(1, 1).setViewPort(Float.NaN, 1f, 0f, 1f);
181+
}
182+
183+
/**
184+
* Verifies that setViewPort() with right = NaN throws an
185+
* IllegalArgumentException.
186+
*/
187+
@Test(expected = IllegalArgumentException.class)
188+
public void iaeCase14() {
189+
new Camera(1, 1).setViewPort(0f, Float.NaN, 0f, 1f);
190+
}
191+
192+
/**
193+
* Verifies that setViewPort() with bottom = NaN throws an
194+
* IllegalArgumentException.
195+
*/
196+
@Test(expected = IllegalArgumentException.class)
197+
public void iaeCase15() {
198+
new Camera(1, 1).setViewPort(0f, 1f, Float.NaN, 1f);
199+
}
200+
201+
/**
202+
* Verifies that setViewPort() with top = NaN throws an
203+
* IllegalArgumentException.
204+
*/
205+
@Test(expected = IllegalArgumentException.class)
206+
public void iaeCase16() {
207+
new Camera(1, 1).setViewPort(0f, 1f, 0f, Float.NaN);
208+
}
209+
210+
/**
211+
* Verifies that setViewPortBottom(NaN) throws an IllegalArgumentException.
212+
*/
213+
@Test(expected = IllegalArgumentException.class)
214+
public void iaeCase17() {
215+
new Camera(1, 1).setViewPortBottom(Float.NaN);
216+
}
217+
218+
/**
219+
* Verifies that setViewPortLeft(NaN) throws an IllegalArgumentException.
220+
*/
221+
@Test(expected = IllegalArgumentException.class)
222+
public void iaeCase18() {
223+
new Camera(1, 1).setViewPortLeft(Float.NaN);
224+
}
225+
226+
/**
227+
* Verifies that setViewPortRight(NaN) throws an IllegalArgumentException.
228+
*/
229+
@Test(expected = IllegalArgumentException.class)
230+
public void iaeCase19() {
231+
new Camera(1, 1).setViewPortRight(Float.NaN);
232+
}
233+
234+
/**
235+
* Verifies that setViewPortTop(NaN) throws an IllegalArgumentException.
236+
*/
237+
@Test(expected = IllegalArgumentException.class)
238+
public void iaeCase20() {
239+
new Camera(1, 1).setViewPortTop(Float.NaN);
240+
}
241+
}

0 commit comments

Comments
 (0)