diff options
author | Sven Göthel <[email protected]> | 2024-01-19 06:11:46 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-19 06:11:46 +0100 |
commit | 1040bed4ecc6f4598ea459f1073a9240583fc3c3 (patch) | |
tree | 4d940115be7b5967553b9b93480abb7321da51ea /src/jogl/classes | |
parent | 7e582cbe21084e2b4b624761a411259da270ce26 (diff) |
Add Cube to Frustum Plane mapping, supporting transformation of object-space AABBox into model-view Cube to Frustum.Plane for culling (cpu) and clipping (gpu)
Diffstat (limited to 'src/jogl/classes')
-rw-r--r-- | src/jogl/classes/com/jogamp/math/geom/Cube.java | 228 | ||||
-rw-r--r-- | src/jogl/classes/com/jogamp/math/geom/Frustum.java | 24 |
2 files changed, 251 insertions, 1 deletions
diff --git a/src/jogl/classes/com/jogamp/math/geom/Cube.java b/src/jogl/classes/com/jogamp/math/geom/Cube.java new file mode 100644 index 000000000..ded963a04 --- /dev/null +++ b/src/jogl/classes/com/jogamp/math/geom/Cube.java @@ -0,0 +1,228 @@ +/** + * Copyright 2024 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.math.geom; + +import com.jogamp.math.Matrix4f; +import com.jogamp.math.Vec3f; + +/** + * Simple 8-point {@link Vec3f} cube compound having {@code z-far <= z-near} + * <p> + * 8-points from far to near (z), left to right (x) and bottom to top (y) in AABB case, otherwise arbitrary + * <ul> + * <li>lbf, rbf, rtf, ltf</li> + * <li>lbn, rbn, rtn, ltn</li> + * </ul> + * </p> + * <p> + * A cube can be used to transform an {@link AABBox} + * from object-space to e.g. model-view (Mv) space via {@link #Cube(AABBox)} and {@link #transform(Matrix4f)} + * as required for an Mv {@link Frustum} presentation, see {@link #updateFrustumPlanes(Frustum)}. + * </p> + */ +public class Cube { + /** left -bottom-far (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f lbf; + /** right-bottom-far (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f rbf; + /** right-top -far (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f rtf; + /** left -top -far (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f ltf; + + /** left -bottom-near (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f lbn; + /** right-bottom-near (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f rbn; + /** right-top -near (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f rtn; + /** left -top -near (xyz) in AABB case, otherwise arbitrary */ + public final Vec3f ltn; + + @Override + public final String toString() { + return "[lbf "+lbf+", rbf "+rbf+", rtf "+rtf+", lbn "+lbn+", rbn "+rbn+", rtn "+rtn+", ltn "+ltn+"]"; + } + + /** + * Construct a {@link Cube} with all points set to zero. + */ + public Cube() { + lbf = new Vec3f(); + rbf = new Vec3f(); + rtf = new Vec3f(); + ltf = new Vec3f(); + + lbn = new Vec3f(); + rbn = new Vec3f(); + rtn = new Vec3f(); + ltn = new Vec3f(); + } + + /** Copy construct for a {@link Cube}. */ + public Cube(final Cube o) { + lbf = new Vec3f(o.lbf); + rbf = new Vec3f(o.rbf); + rtf = new Vec3f(o.rtf); + ltf = new Vec3f(o.ltf); + + lbn = new Vec3f(o.lbn); + rbn = new Vec3f(o.rbn); + rtn = new Vec3f(o.rtn); + ltn = new Vec3f(o.ltn); + } + + /** Construct a {@link Cube} with given {@link AABBox}. */ + public Cube(final AABBox box) { + this( box.getLow(), box.getHigh()); + } + + /** + * Construct a {@link Cube} with given {@link AABBox} minimum and maximum. + * @param lo_lbf minimum left -bottom-far (xyz) + * @param hi_rtn maximum right-top -near (xyz) + */ + public Cube(final Vec3f lo_lbf, final Vec3f hi_rtn) { + lbf = new Vec3f(lo_lbf); + rtn = new Vec3f(hi_rtn); + + rbf = new Vec3f(rtn.x(), lbf.y(), lbf.z()); + rtf = new Vec3f(rtn.x(), rtn.y(), lbf.z()); + ltf = new Vec3f(lbf.x(), rtn.y(), lbf.z()); + + lbn = new Vec3f(lbf.x(), lbf.y(), rtn.z()); + rbn = new Vec3f(rtn.x(), lbf.y(), rtn.z()); + ltn = new Vec3f(lbf.x(), rtn.y(), rtn.z()); + } + + /** + * Setting this cube to given {@link AABBox} minimum and maximum. + */ + public Cube set(final AABBox box) { + return set( box.getLow(), box.getHigh()); + } + + /** + * Setting this cube to given {@link AABBox} minimum and maximum. + * @param lo_lbf minimum left -bottom-far (xyz) + * @param hi_rtn maximum right-top -near (xyz) + */ + public Cube set(final Vec3f lo_lbf, final Vec3f hi_rtn) { + lbf.set(lo_lbf); + rtn.set(hi_rtn); + + rbf.set(rtn.x(), lbf.y(), lbf.z()); + rtf.set(rtn.x(), rtn.y(), lbf.z()); + ltf.set(lbf.x(), rtn.y(), lbf.z()); + + lbn.set(lbf.x(), lbf.y(), rtn.z()); + rbn.set(rtn.x(), lbf.y(), rtn.z()); + ltn.set(lbf.x(), rtn.y(), rtn.z()); + return this; + } + + public Cube set(final Cube o) { + lbf.set(o.lbf); + rbf.set(o.rbf); + rtf.set(o.rtf); + ltf.set(o.ltf); + + lbn.set(o.lbn); + rbn.set(o.rbn); + rtn.set(o.rtn); + ltn.set(o.ltn); + return this; + } + + /** Affine 3f-vector transformation of all 8-points with given matrix, {@link Matrix4f#mulVec3f(Vec3f)}. */ + public Cube transform(final Matrix4f mat) { + mat.mulVec3f(lbf); + mat.mulVec3f(rbf); + mat.mulVec3f(rtf); + mat.mulVec3f(ltf); + + mat.mulVec3f(lbn); + mat.mulVec3f(rbn); + mat.mulVec3f(rtn); + mat.mulVec3f(ltn); + return this; + } + + /** + * Calculate the frustum planes using this {@link Cube}. + * <p> + * One useful application is to {@link Cube#transform(Matrix4f) transform} + * an {@link AABBox}, see {@link Cube#Cube(AABBox)} from its object-space + * into model-view (Mv) and produce the {@link Frustum} planes using this method + * for CPU side object culling and GPU shader side fragment clipping. + * </p> + * <p> + * Frustum plane's normals will point to the inside of the viewing frustum, + * as required by the {@link Frustum} class. + * </p> + * @param frustum the output frustum + * @return the output frustum for chaining + * @see Frustum#updateFrustumPlanes(Cube) + * @see Cube#Cube(AABBox) + * @see Cube#transform(Matrix4f) + */ + public Frustum updateFrustumPlanes(final Frustum frustum) { + // n [ 0.0 / 0.0 / -1.0 ] + frustum.getPlanes()[Frustum.NEAR].set( + (lbf).minus(lbn).normalize(), // | lbf - lbn |, inwards + lbn ); // closest AABB point to origin on plane + + // n [ 0.0 / 0.0 / 1.0 ] + frustum.getPlanes()[Frustum.FAR].set( + (lbn).minus(lbf).normalize(), // | lbn - lbf |, inwards + lbf ); // closest AABB point to origin on plane + + // n [ 1.0 / 0.0 / 0.0 ] + frustum.getPlanes()[Frustum.LEFT].set( + (rbf).minus(lbf).normalize(), // | rbf - lbf |, inwards + lbn ); // closest AABB point to origin on plane + + // n [ -1.0 / 0.0 / 0.0 ] + frustum.getPlanes()[Frustum.RIGHT].set( + (lbf).minus(rbf).normalize(), // | lbf - rbf |, inwards + rbn ); // closest AABB point to origin on plane + + // n [ 0.0 / 1.0 / 0.0 ] + frustum.getPlanes()[Frustum.BOTTOM].set( + (ltf).minus(lbf).normalize(), // | ltf - lbf |, inwards + lbn ); // closest AABB point to origin on plane + + // n [ 0.0 / -1.0 / 0.0 ] + frustum.getPlanes()[Frustum.TOP].set( + (lbf).minus(ltf).normalize(), // | lbf - ltf |, inwards + ltn ); // closest AABB point to origin on plane + + return frustum; + } + +} diff --git a/src/jogl/classes/com/jogamp/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/math/geom/Frustum.java index 9e9f65c31..991e70aac 100644 --- a/src/jogl/classes/com/jogamp/math/geom/Frustum.java +++ b/src/jogl/classes/com/jogamp/math/geom/Frustum.java @@ -255,7 +255,29 @@ public class Frustum { pmv.updateFrustumPlanes(this); } - private static final boolean isOutsideImpl(final Plane p, final AABBox box) { + /** + * Calculate the frustum planes using the given {@link Cube}. + * <p> + * One useful application is to {@link Cube#transform(Matrix4f) transform} + * an {@link AABBox}, see {@link Cube#Cube(AABBox)} from its object-space + * into model-view (Mv) and produce the {@link Frustum} planes using this method + * for CPU side object culling and GPU shader side fragment clipping. + * </p> + * <p> + * Frustum plane's normals will point to the inside of the viewing frustum, + * as required by this class. + * </p> + * @param c the {@link Cube} source + * @return this frustum for chaining + * @see Cube#updateFrustumPlanes(Frustum) + * @see Cube#Cube(AABBox) + * @see Cube#transform(Matrix4f) + */ + public Frustum updateFrustumPlanes(final Cube c) { + return c.updateFrustumPlanes(this); + } + + private static final boolean isOutsideImpl(final Plane p, final AABBox box) { final Vec3f lo = box.getLow(); final Vec3f hi = box.getHigh(); |