159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.math;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>LineSegment represents a segment in the space. This is a portion of a Line
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * that has a limited start and end points.</p>
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>A LineSegment is defined by an origin, a direction and an extent (or length).
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Direction should be a normalized vector. It is not internally normalized.</p>
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>This class provides methods to calculate distances between LineSegments, Rays and Vectors.
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * It is also possible to retrieve both end points of the segment {@link LineSegment#getPositiveEnd(Vector3f)}
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and {@link LineSegment#getNegativeEnd(Vector3f)}. There are also methods to check whether
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a point is within the segment bounds.</p>
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Ray
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Joshua Slack
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class LineSegment implements Cloneable, Savable, java.io.Serializable {
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    static final long serialVersionUID = 1;
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f origin;
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f direction;
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float extent;
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LineSegment() {
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        origin = new Vector3f();
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        direction = new Vector3f();
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LineSegment(LineSegment ls) {
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.origin = new Vector3f(ls.getOrigin());
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.direction = new Vector3f(ls.getDirection());
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.extent = ls.getExtent();
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>Creates a new LineSegment with the given origin, direction and extent.</p>
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>Note that the origin is not one of the ends of the LineSegment, but its center.</p>
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LineSegment(Vector3f origin, Vector3f direction, float extent) {
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.origin = origin;
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.direction = direction;
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.extent = extent;
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>Creates a new LineSegment with a given origin and end. This constructor will calculate the
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * center, the direction and the extent.</p>
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LineSegment(Vector3f start, Vector3f end) {
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.origin = new Vector3f(0.5f * (start.x + end.x), 0.5f * (start.y + end.y), 0.5f * (start.z + end.z));
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.direction = end.subtract(start);
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.extent = direction.length() * 0.5f;
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        direction.normalizeLocal();
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void set(LineSegment ls) {
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.origin = new Vector3f(ls.getOrigin());
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.direction = new Vector3f(ls.getDirection());
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.extent = ls.getExtent();
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distance(Vector3f point) {
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.sqrt(distanceSquared(point));
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distance(LineSegment ls) {
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.sqrt(distanceSquared(ls));
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distance(Ray r) {
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.sqrt(distanceSquared(r));
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distanceSquared(Vector3f point) {
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f compVec1 = vars.vect1;
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        point.subtract(origin, compVec1);
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float segmentParameter = direction.dot(compVec1);
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (-extent < segmentParameter) {
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (segmentParameter < extent) {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                origin.add(direction.mult(segmentParameter, compVec1),
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        compVec1);
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                origin.add(direction.mult(extent, compVec1), compVec1);
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            origin.subtract(direction.mult(extent, compVec1), compVec1);
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        compVec1.subtractLocal(point);
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float len = compVec1.lengthSquared();
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return len;
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distanceSquared(LineSegment test) {
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f compVec1 = vars.vect1;
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        origin.subtract(test.getOrigin(), compVec1);
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float negativeDirectionDot = -(direction.dot(test.getDirection()));
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float diffThisDot = compVec1.dot(direction);
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float diffTestDot = -(compVec1.dot(test.getDirection()));
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float lengthOfDiff = compVec1.lengthSquared();
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float determinant = FastMath.abs(1.0f - negativeDirectionDot
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                * negativeDirectionDot);
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float s0, s1, squareDistance, extentDeterminant0, extentDeterminant1, tempS0, tempS1;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (determinant >= FastMath.FLT_EPSILON) {
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // segments are not parallel
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            s0 = negativeDirectionDot * diffTestDot - diffThisDot;
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            s1 = negativeDirectionDot * diffThisDot - diffTestDot;
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            extentDeterminant0 = extent * determinant;
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            extentDeterminant1 = test.getExtent() * determinant;
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (s0 >= -extentDeterminant0) {
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (s0 <= extentDeterminant0) {
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (s1 >= -extentDeterminant1) {
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (s1 <= extentDeterminant1) // region 0 (interior)
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        {
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            // minimum at two interior points of 3D lines
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            float inverseDeterminant = ((float) 1.0)
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    / determinant;
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 *= inverseDeterminant;
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 *= inverseDeterminant;
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s0
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + negativeDirectionDot * s1 + (2.0f) * diffThisDot)
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + s1
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (negativeDirectionDot * s0 + s1 + (2.0f) * diffTestDot)
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else // region 3 (side)
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        {
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = test.getExtent();
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            if (tempS0 < -extent) {
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = -extent;
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s0 * (s0 - (2.0f) * tempS0)
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s1 * (s1 + (2.0f) * diffTestDot)
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else if (tempS0 <= extent) {
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = tempS0;
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = -s0 * s0 + s1
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        * (s1 + (2.0f) * diffTestDot)
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else {
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = extent;
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s0 * (s0 - (2.0f) * tempS0)
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s1 * (s1 + (2.0f) * diffTestDot)
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            }
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else // region 7 (side)
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s1 = -test.getExtent();
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (tempS0 < -extent) {
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = -extent;
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (tempS0 <= extent) {
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = tempS0;
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = -s0 * s0 + s1
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = extent;
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (s1 >= -extentDeterminant1) {
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (s1 <= extentDeterminant1) // region 1 (side)
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        {
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = extent;
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            if (tempS1 < -test.getExtent()) {
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = -test.getExtent();
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else if (tempS1 <= test.getExtent()) {
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = tempS1;
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = -s1 * s1 + s0
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        * (s0 + (2.0f) * diffThisDot)
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else {
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = test.getExtent();
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            }
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else // region 2 (corner)
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        {
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = test.getExtent();
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            if (tempS0 < -extent) {
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = -extent;
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s0 * (s0 - (2.0f) * tempS0)
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s1 * (s1 + (2.0f) * diffTestDot)
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else if (tempS0 <= extent) {
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = tempS0;
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = -s0 * s0 + s1
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        * (s1 + (2.0f) * diffTestDot)
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else {
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s0 = extent;
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                if (tempS1 < -test.getExtent()) {
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    s1 = -test.getExtent();
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    squareDistance = s1
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            * (s1 - (2.0f) * tempS1) + s0
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            * (s0 + (2.0f) * diffThisDot)
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            + lengthOfDiff;
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                } else if (tempS1 <= test.getExtent()) {
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    s1 = tempS1;
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    squareDistance = -s1 * s1 + s0
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            * (s0 + (2.0f) * diffThisDot)
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            + lengthOfDiff;
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                } else {
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    s1 = test.getExtent();
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    squareDistance = s1
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            * (s1 - (2.0f) * tempS1) + s0
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            * (s0 + (2.0f) * diffThisDot)
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                            + lengthOfDiff;
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                }
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            }
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else // region 8 (corner)
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s1 = -test.getExtent();
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (tempS0 < -extent) {
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = -extent;
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (tempS0 <= extent) {
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = tempS0;
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = -s0 * s0 + s1
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = extent;
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            if (tempS1 > test.getExtent()) {
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = test.getExtent();
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else if (tempS1 >= -test.getExtent()) {
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = tempS1;
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = -s1 * s1 + s0
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        * (s0 + (2.0f) * diffThisDot)
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else {
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = -test.getExtent();
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            }
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (s1 >= -extentDeterminant1) {
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (s1 <= extentDeterminant1) // region 5 (side)
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s0 = -extent;
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (tempS1 < -test.getExtent()) {
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = -test.getExtent();
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (tempS1 <= test.getExtent()) {
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = tempS1;
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = -s1 * s1 + s0
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = test.getExtent();
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else // region 4 (corner)
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s1 = test.getExtent();
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (tempS0 > extent) {
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = extent;
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (tempS0 >= -extent) {
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = tempS0;
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = -s0 * s0 + s1
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s1 + (2.0f) * diffTestDot)
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s0 = -extent;
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            if (tempS1 < -test.getExtent()) {
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = -test.getExtent();
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else if (tempS1 <= test.getExtent()) {
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = tempS1;
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = -s1 * s1 + s0
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        * (s0 + (2.0f) * diffThisDot)
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            } else {
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                s1 = test.getExtent();
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                squareDistance = s1 * (s1 - (2.0f) * tempS1)
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + s0 * (s0 + (2.0f) * diffThisDot)
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                        + lengthOfDiff;
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            }
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else // region 6 (corner)
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                {
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    s1 = -test.getExtent();
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (tempS0 > extent) {
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s0 = extent;
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (s1 + (2.0f) * diffTestDot) + lengthOfDiff;
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else if (tempS0 >= -extent) {
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s0 = tempS0;
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        squareDistance = -s0 * s0 + s1
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (s1 + (2.0f) * diffTestDot) + lengthOfDiff;
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        s0 = -extent;
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (tempS1 < -test.getExtent()) {
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = -test.getExtent();
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (tempS1 <= test.getExtent()) {
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = tempS1;
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = -s1 * s1 + s0
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            s1 = test.getExtent();
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (s0 + (2.0f) * diffThisDot)
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    + lengthOfDiff;
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // The segments are parallel. The average b0 term is designed to
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // ensure symmetry of the function. That is, dist(seg0,seg1) and
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // dist(seg1,seg0) should produce the same number.get
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float extentSum = extent + test.getExtent();
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float sign = (negativeDirectionDot > 0.0f ? -1.0f : 1.0f);
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float averageB0 = (0.5f) * (diffThisDot - sign * diffTestDot);
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float lambda = -averageB0;
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (lambda < -extentSum) {
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                lambda = -extentSum;
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (lambda > extentSum) {
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                lambda = extentSum;
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            squareDistance = lambda * (lambda + (2.0f) * averageB0)
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + lengthOfDiff;
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.abs(squareDistance);
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distanceSquared(Ray r) {
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f kDiff = r.getOrigin().subtract(origin);
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fA01 = -r.getDirection().dot(direction);
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fB0 = kDiff.dot(r.getDirection());
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fB1 = -kDiff.dot(direction);
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fC = kDiff.lengthSquared();
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fDet = FastMath.abs(1.0f - fA01 * fA01);
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float fS0, fS1, fSqrDist, fExtDet;
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fDet >= FastMath.FLT_EPSILON) {
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // The ray and segment are not parallel.
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fS0 = fA01 * fB1 - fB0;
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fS1 = fA01 * fB0 - fB1;
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fExtDet = extent * fDet;
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fS0 >= (float) 0.0) {
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (fS1 >= -fExtDet) {
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fS1 <= fExtDet) // region 0
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        // minimum at interior points of ray and segment
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        float fInvDet = ((float) 1.0) / fDet;
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS0 *= fInvDet;
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 *= fInvDet;
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = fS0
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (fS0 + fA01 * fS1 + ((float) 2.0) * fB0)
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                + fS1
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (fA01 * fS0 + fS1 + ((float) 2.0) * fB1) + fC;
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else // region 1
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    {
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = extent;
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS0 = -(fA01 * fS1 + fB0);
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (fS0 > (float) 0.0) {
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fSqrDist = -fS0 * fS0 + fS1
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                    * (fS1 + ((float) 2.0) * fB1) + fC;
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else {
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fS0 = (float) 0.0;
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else // region 5
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                {
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS1 = -extent;
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS0 = -(fA01 * fS1 + fB0);
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fS0 > (float) 0.0) {
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = -fS0 * fS0 + fS1
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (fS1 + ((float) 2.0) * fB1) + fC;
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS0 = (float) 0.0;
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (fS1 <= -fExtDet) // region 4
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                {
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS0 = -(-fA01 * extent + fB0);
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fS0 > (float) 0.0) {
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = -extent;
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = -fS0 * fS0 + fS1
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (fS1 + ((float) 2.0) * fB1) + fC;
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS0 = (float) 0.0;
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = -fB1;
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (fS1 < -extent) {
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fS1 = -extent;
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (fS1 > extent) {
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fS1 = extent;
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (fS1 <= fExtDet) // region 3
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                {
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS0 = (float) 0.0;
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS1 = -fB1;
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fS1 < -extent) {
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = -extent;
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else if (fS1 > extent) {
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = extent;
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else // region 2
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                {
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fS0 = -(fA01 * extent + fB0);
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fS0 > (float) 0.0) {
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = extent;
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = -fS0 * fS0 + fS1
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                * (fS1 + ((float) 2.0) * fB1) + fC;
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS0 = (float) 0.0;
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fS1 = -fB1;
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (fS1 < -extent) {
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fS1 = -extent;
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        } else if (fS1 > extent) {
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fS1 = extent;
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // ray and segment are parallel
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fA01 > (float) 0.0) {
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // opposite direction vectors
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fS1 = -extent;
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // same direction vectors
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fS1 = extent;
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fS0 = -(fA01 * fS1 + fB0);
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fS0 > (float) 0.0) {
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fSqrDist = -fS0 * fS0 + fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fS0 = (float) 0.0;
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.abs(fSqrDist);
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getDirection() {
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return direction;
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setDirection(Vector3f direction) {
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.direction = direction;
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getExtent() {
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return extent;
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setExtent(float extent) {
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.extent = extent;
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getOrigin() {
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return origin;
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setOrigin(Vector3f origin) {
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.origin = origin;
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // P+e*D
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getPositiveEnd(Vector3f store) {
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return origin.add((direction.mult(extent, store)), store);
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // P-e*D
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getNegativeEnd(Vector3f store) {
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return origin.subtract((direction.mult(extent, store)), store);
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter e) throws IOException {
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule capsule = e.getCapsule(this);
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(origin, "origin", Vector3f.ZERO);
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(direction, "direction", Vector3f.ZERO);
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(extent, "extent", 0);
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter e) throws IOException {
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule capsule = e.getCapsule(this);
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone());
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone());
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        extent = capsule.readFloat("extent", 0);
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LineSegment clone() {
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        try {
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            LineSegment segment = (LineSegment) super.clone();
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            segment.direction = direction.clone();
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            segment.origin = origin.clone();
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return segment;
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } catch (CloneNotSupportedException e) {
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new AssertionError();
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * that contains this LineSegment.</p><p>This function is float error aware.</p>
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isPointInsideBounds(Vector3f point) {
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return isPointInsideBounds(point, Float.MIN_VALUE);
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * that contains this LineSegment.</p><p>This function accepts an error parameter, which
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * is added to the extent of the bounding box.</p>
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isPointInsideBounds(Vector3f point, float error) {
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (FastMath.abs(point.x - origin.x) > FastMath.abs(direction.x * extent) + error) {
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (FastMath.abs(point.y - origin.y) > FastMath.abs(direction.y * extent) + error) {
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (FastMath.abs(point.z - origin.z) > FastMath.abs(direction.z * extent) + error) {
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return true;
63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
632