frustum.java

来自「world wind java sdk 源码」· Java 代码 · 共 385 行

JAVA
385
字号
/*Copyright (C) 2001, 2006 United States Governmentas represented by the Administrator of theNational Aeronautics and Space Administration.All Rights Reserved.*/package gov.nasa.worldwind.geom;import gov.nasa.worldwind.util.Logging;//todo: check javadoc accuracy,/** * Instances of <code>Frustum</code> are immutable. </p> * * @author Tom Gaskins * @version $Id: Frustum.java 3301 2007-10-16 00:31:34Z dcollins $ */public class Frustum{    private final Plane left;    private final Plane right;    private final Plane bottom;    private final Plane top;    private final Plane near;    private final Plane far;    private final Plane[] allPlanes;    /**     * Create a default frustum with six <code>Plane</code>s. This defines a box of dimension (2, 2, 2) centered at the     * origin.     */    public Frustum()    {        this(            new Plane(1, 0, 0, 1),  // Left            new Plane(-1, 0, 0, 1),  // Right            new Plane(0, 1, 0, 1),  // Bottom            new Plane(0, -1, 0, 1),  // Top            new Plane(0, 0, -1, 1),  // Near            new Plane(0, 0, 1, 1)); // Far    }    /**     * Create a frustum from six <code>Plane</code>s, which define its boundaries. Does not except null arguments.     *     * @param near   the near plane     * @param far    the far plane     * @param left   the left side of the view frustum     * @param right  the right side of the view frustm     * @param top    the top of the view frustum     * @param bottom the bottom of the view frustum     * @throws IllegalArgumentException if any argument is null     */    public Frustum(Plane left, Plane right, Plane bottom, Plane top, Plane near, Plane far)    {        if (left == null || right == null || bottom == null || top == null || near == null || far == null)        {            String message = Logging.getMessage("nullValue.PlaneIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.left = left;        this.right = right;        this.bottom = bottom;        this.top = top;        this.near = near;        this.far = far;        this.allPlanes = new Plane[] {this.left, this.right, this.bottom, this.top, this.near, this.far};    }    public boolean equals(Object obj)    {        if (this == obj)            return true;        if (obj == null || getClass() != obj.getClass())            return false;        Frustum that = (Frustum) obj;        return this.left.equals(that.left)            && this.right.equals(that.right)            && this.bottom.equals(that.bottom)            && this.top.equals(that.top)            && this.near.equals(that.near)            && this.far.equals(that.far);    }    public final Plane getLeft()    {        return this.left;    }    public final Plane getRight()    {        return this.right;    }    public final Plane getBottom()    {        return this.bottom;    }    public final Plane getTop()    {        return this.top;    }    public final Plane getNear()    {        return this.near;    }    public final Plane getFar()    {        return this.far;    }    public Plane[] getAllPlanes()    {        return this.allPlanes;    }    public int hashCode()    {        int result;        result = this.left.hashCode();        result = 31 * result + this.right.hashCode();        result = 19 * result + this.bottom.hashCode();        result = 23 * result + this.top.hashCode();        result = 17 * result + this.near.hashCode();        result = 19 * result + this.far.hashCode();        return result;    }    public String toString()    {        StringBuilder sb = new StringBuilder();        sb.append("(");        sb.append("left=").append(this.near);        sb.append(", right=").append(this.near);        sb.append(", bottom=").append(this.near);        sb.append(", top=").append(this.near);        sb.append(", near=").append(this.near);        sb.append(", far=").append(this.near);        sb.append(")");        return sb.toString();    }    // ============== Factory Functions ======================= //    // ============== Factory Functions ======================= //    // ============== Factory Functions ======================= //    public static Frustum fromProjectionMatrix(Matrix projectionMatrix)    {        //noinspection UnnecessaryLocalVariable        Matrix m = projectionMatrix;        if (m == null)        {            String message = Logging.getMessage("nullValue.MatrixIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        // Extract the left clipping plane from the projection-matrix.        double leftMag = Math.sqrt((m.m41 + m.m11) * (m.m41 + m.m11) + (m.m42 + m.m12) * (m.m42 + m.m12)            + (m.m43 + m.m13) * (m.m43 + m.m13));        Plane leftPlane = new Plane((m.m41 + m.m11) / leftMag, (m.m42 + m.m12) / leftMag, (m.m43 + m.m13) / leftMag,            m.m44 + m.m14);        // Extract the right clipping plane from the projection-matrix.        double rightMag = Math.sqrt((m.m41 - m.m11) * (m.m41 - m.m11) + (m.m42 - m.m12) * (m.m42 - m.m12)            + (m.m43 - m.m13) * (m.m43 - m.m13));        Plane rightPlane = new Plane((m.m41 - m.m11) / rightMag, (m.m42 - m.m12) / rightMag, (m.m43 - m.m13) / rightMag,            m.m44 - m.m14);        // Extract the bottom clipping plane from the projection-matrix.        double bottomMag = Math.sqrt((m.m41 + m.m21) * (m.m41 + m.m21) + (m.m42 + m.m22) * (m.m42 + m.m22)            + (m.m43 + m.m23) * (m.m43 + m.m23));        Plane bottomPlane = new Plane((m.m41 + m.m21) / bottomMag, (m.m42 + m.m22) / bottomMag,            (m.m43 + m.m23) / bottomMag,            m.m44 + m.m24);        // Extract the top clipping plane from the projection-matrix.        double topMag = Math.sqrt((m.m41 - m.m21) * (m.m41 - m.m21) + (m.m42 - m.m22) * (m.m42 - m.m22)            + (m.m43 - m.m23) * (m.m43 - m.m23));        Plane topPlane = new Plane((m.m41 - m.m21) / topMag, (m.m42 - m.m22) / topMag, (m.m43 - m.m23) / topMag,            m.m44 - m.m24);        // Extract the near clipping plane from the projection-matrix.        double nearMag = Math.sqrt((m.m41 + m.m31) * (m.m41 + m.m31) + (m.m42 + m.m32) * (m.m42 + m.m32)            + (m.m43 + m.m33) * (m.m43 + m.m33));        Plane nearPlane = new Plane((m.m41 + m.m31) / nearMag, (m.m42 + m.m32) / nearMag, (m.m43 + m.m33) / nearMag,            m.m44 + m.m34);        // Extract the far clipping plane from the projection-matrix.        double farMag = Math.sqrt((m.m41 - m.m31) * (m.m41 - m.m31) + (m.m42 - m.m32) * (m.m42 - m.m32)            + (m.m43 - m.m33) * (m.m43 - m.m33));        Plane farPlane = new Plane((m.m41 - m.m31) / farMag, (m.m42 - m.m32) / farMag, (m.m43 - m.m33) / farMag,            m.m44 - m.m34);        return new Frustum(leftPlane, rightPlane, bottomPlane, topPlane, nearPlane, farPlane);    }    /**     * Creates a <code>Frustum</code> from a horizontal field-of-view, viewport aspect ratio and distance to near and     * far depth clipping planes. The near plane must be closer than the far plane, and both planes must be a positive     * distance away.     *     * @param horizontalFieldOfView horizontal field-of-view angle in the range (0, 180)     * @param viewportWidth         the width of the viewport in screen pixels     * @param viewportHeight        the height of the viewport in screen pixels     * @param near                  distance to the near depth clipping plane     * @param far                   distance to far depth clipping plane     * @throws IllegalArgumentException if fov is not in the range (0, 180), if either near or far are negative, or near     *                                  is greater than or equal to far     */    public static Frustum fromPerspective(Angle horizontalFieldOfView, int viewportWidth, int viewportHeight,        double near, double far)    {        if (horizontalFieldOfView == null)        {            String message = Logging.getMessage("Geom.ViewFrustum.FieldOfViewIsNull");            Logging.logger().fine(message);            throw new IllegalArgumentException(message);        }        double fov = horizontalFieldOfView.getDegrees();        double farMinusNear = far - near;        String message = null;        if (fov <= 0 || fov > 180)            message = Logging.getMessage("Geom.ViewFrustum.FieldOfViewOutOfRange", fov);        if (near <= 0 || farMinusNear <= 0)            message = Logging.getMessage("Geom.ViewFrusutm.ClippingDistanceOutOfRange");        if (message != null)        {            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        double focalLength = 1d / horizontalFieldOfView.tanHalfAngle();        double aspect = viewportHeight / (double) viewportWidth;        double lrLen = Math.sqrt(focalLength * focalLength + 1);        double btLen = Math.sqrt(focalLength * focalLength + aspect * aspect);        Plane leftPlane = new Plane(focalLength / lrLen, 0d, 0d - 1d / lrLen, 0);        Plane rightPlane = new Plane(0d - focalLength / lrLen, 0d, 0d - 1d / lrLen, 0d);        Plane bottomPlane = new Plane(0d, focalLength / btLen, 0d - aspect / btLen, 0d);        Plane topPlane = new Plane(0d, 0d - focalLength / btLen, 0d - aspect / btLen, 0d);        Plane nearPlane = new Plane(0d, 0d, 0d - 1d, 0d - near);        Plane farPlane = new Plane(0d, 0d, 1d, far);        return new Frustum(leftPlane, rightPlane, bottomPlane, topPlane, nearPlane, farPlane);    }    /**     * Creates a <code>Frustum</code> from three sets of parallel clipping planes (a parallel projectionMatrix). In this     * case, the near and far depth clipping planes may be a negative distance away.     *     * @param near   distance to the near depth clipping plane     * @param far    distance to far depth clipping plane     * @param width  horizontal dimension of the near clipping plane     * @param height vertical dimension of the near clipping plane     * @throws IllegalArgumentException if the difference of any plane set (lright - left, top - bottom, far - near) is     *                                  less than or equal to zero.     */    public static Frustum fromPerspective(double width, double height, double near, double far)    {        double farMinusNear = far - near;        if (farMinusNear <= 0.0 || width <= 0.0 || height <= 0.0)        {            String message = Logging.getMessage("Geom.ViewFrusutm.ClippingDistanceOutOfRange");            Logging.logger().fine(message);            throw new IllegalArgumentException(message);        }        double width_over_2 = width / 2.0;        double height_over_2 = height / 2.0;        Plane leftPlane = new Plane(1.0, 0.0, 0.0, width_over_2);        Plane rightPlane = new Plane(-1.0, 0.0, 0.0, width_over_2);        Plane bottomPlane = new Plane(0.0, 1.0, 0.0, height_over_2);        Plane topPlane = new Plane(0.0, -1.0, 0.0, height_over_2);        Plane nearPlane = new Plane(0.0, 0.0, -1.0, (near < 0.0) ? near : -near);        Plane farPlane = new Plane(0.0, 0.0, 1.0, (far < 0.0) ? -far : far);        return new Frustum(leftPlane, rightPlane, bottomPlane, topPlane, nearPlane, farPlane);    }    // ============== Intersection Functions ======================= //    // ============== Intersection Functions ======================= //    // ============== Intersection Functions ======================= //    /**     * @param extent     * @return     * @throws IllegalArgumentException if <code>extent</code> is null     */    public final boolean intersects(Extent extent)    {        if (extent == null)        {            String msg = Logging.getMessage("nullValue.ExtentIsNull");            Logging.logger().fine(msg);            throw new IllegalArgumentException(msg);        }        // See if the extent's bounding sphere is within or intersects the frustum.        Vec4 c = extent.getCenter();        double nr = -extent.getRadius();        if (this.far.dot(c) <= nr)            return false;        if (this.left.dot(c) <= nr)            return false;        if (this.right.dot(c) <= nr)            return false;        if (this.top.dot(c) <= nr)            return false;        if (this.bottom.dot(c) <= nr)            return false;        //noinspection RedundantIfStatement        if (this.near.dot(c) <= nr)            return false;        return true;    }    /**     * @param point     * @return     * @throws IllegalArgumentException if <code>point</code> is null     */    public final boolean contains(Vec4 point)    {        if (point == null)        {            String msg = Logging.getMessage("nullValue.PointIsNull");            Logging.logger().fine(msg);            throw new IllegalArgumentException(msg);        }        if (this.far.dot(point) <= 0)            return false;        if (this.left.dot(point) <= 0)            return false;        if (this.right.dot(point) <= 0)            return false;        if (this.top.dot(point) <= 0)            return false;        if (this.bottom.dot(point) <= 0)            return false;        //noinspection RedundantIfStatement        if (this.near.dot(point) <= 0)            return false;        return true;    }    // ============== Geometric Functions ======================= //    // ============== Geometric Functions ======================= //    // ============== Geometric Functions ======================= //    /**     * @param matrix     * @return     * @throws IllegalArgumentException if <code>matrix</code> is null     */    public Frustum transformBy(Matrix matrix)    {        ensureNonNull(matrix);        Plane left = new Plane(this.left.getVector().transformBy4(matrix));        Plane right = new Plane(this.right.getVector().transformBy4(matrix));        Plane bottom = new Plane(this.bottom.getVector().transformBy4(matrix));        Plane top = new Plane(this.top.getVector().transformBy4(matrix));        Plane near = new Plane(this.near.getVector().transformBy4(matrix));        Plane far = new Plane(this.far.getVector().transformBy4(matrix));        return new Frustum(left, right, bottom, top, near, far);    }    // ============== Helper Functions ======================= //    // ============== Helper Functions ======================= //    // ============== Helper Functions ======================= //    private static void ensureNonNull(Matrix matrix)    {        if (matrix == null)        {            String msg = Logging.getMessage("nullValue.MatrixIsNull");            Logging.logger().fine(msg);            throw new IllegalArgumentException(msg);        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?