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.bounding;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.Collidable;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResult;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResults;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.UnsupportedCollisionException;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.*;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//import com.jme.scene.TriMesh;
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>BoundingBox</code> defines an axis-aligned cube that defines a
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * container for a group of vertices of a particular piece of geometry. This box
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defines a center and extents from that center along the x, y and z axis. <br>
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <br>
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A typical usage is to allow the class define the center and radius by calling
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * either <code>containAABB</code> or <code>averagePoints</code>. A call to
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>computeFramePoint</code> in turn calls <code>containAABB</code>.
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Joshua Slack
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @version $Id: BoundingBox.java,v 1.50 2007/09/22 16:46:35 irrisor Exp $
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class BoundingBox extends BoundingVolume {
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    float xExtent, yExtent, zExtent;
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default constructor instantiates a new <code>BoundingBox</code>
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * object.
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingBox() {
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Contstructor instantiates a new <code>BoundingBox</code> object with
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * given specs.
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingBox(Vector3f c, float x, float y, float z) {
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.center.set(c);
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.xExtent = x;
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.yExtent = y;
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.zExtent = z;
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingBox(BoundingBox source) {
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.center.set(source.center);
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.xExtent = source.xExtent;
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.yExtent = source.yExtent;
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.zExtent = source.zExtent;
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingBox(Vector3f min, Vector3f max) {
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setMinMax(min, max);
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Type getType() {
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return Type.AABB;
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>computeFromPoints</code> creates a new Bounding Box from a given
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * set of points. It uses the <code>containAABB</code> method as default.
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param points
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the points to contain.
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void computeFromPoints(FloatBuffer points) {
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        containAABB(points);
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>computeFromTris</code> creates a new Bounding Box from a given
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * set of triangles. It is used in OBBTree calculations.
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param tris
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param start
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param end
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void computeFromTris(Triangle[] tris, int start, int end) {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (end - start <= 0) {
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f min = vars.vect1.set(new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f max = vars.vect2.set(new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f point;
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = start; i < end; i++) {
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = tris[i].get(0);
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = tris[i].get(1);
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = tris[i].get(2);
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.set(min.addLocal(max));
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.multLocal(0.5f);
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = max.x - center.x;
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = max.y - center.y;
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = max.z - center.z;
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void computeFromTris(int[] indices, Mesh mesh, int start, int end) {
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (end - start <= 0) {
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f vect1 = vars.vect1;
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f vect2 = vars.vect2;
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Triangle triangle = vars.triangle;
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f min = vect1.set(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f max = vect2.set(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f point;
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = start; i < end; i++) {
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            mesh.getTriangle(indices[i], triangle);
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = triangle.get(0);
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = triangle.get(1);
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            point = triangle.get(2);
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            checkMinMax(min, max, point);
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.set(min.addLocal(max));
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.multLocal(0.5f);
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = max.x - center.x;
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = max.y - center.y;
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = max.z - center.z;
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static void checkMinMax(Vector3f min, Vector3f max, Vector3f point) {
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.x < min.x) {
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            min.x = point.x;
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.x > max.x) {
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            max.x = point.x;
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.y < min.y) {
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            min.y = point.y;
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.y > max.y) {
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            max.y = point.y;
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.z < min.z) {
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            min.z = point.z;
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (point.z > max.z) {
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            max.z = point.z;
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>containAABB</code> creates a minimum-volume axis-aligned bounding
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * box of the points, then selects the smallest enclosing sphere of the box
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * with the sphere centered at the boxes center.
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param points
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the list of points.
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void containAABB(FloatBuffer points) {
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (points == null) {
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        points.rewind();
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (points.remaining() <= 2) // we need at least a 3 float vector
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        {
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        BufferUtils.populateFromBuffer(vars.vect1, points, 0);
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float minX = vars.vect1.x, minY = vars.vect1.y, minZ = vars.vect1.z;
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float maxX = vars.vect1.x, maxY = vars.vect1.y, maxZ = vars.vect1.z;
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 1, len = points.remaining() / 3; i < len; i++) {
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            BufferUtils.populateFromBuffer(vars.vect1, points, i);
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vars.vect1.x < minX) {
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                minX = vars.vect1.x;
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (vars.vect1.x > maxX) {
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxX = vars.vect1.x;
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vars.vect1.y < minY) {
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                minY = vars.vect1.y;
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (vars.vect1.y > maxY) {
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxY = vars.vect1.y;
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vars.vect1.z < minZ) {
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                minZ = vars.vect1.z;
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (vars.vect1.z > maxZ) {
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxZ = vars.vect1.z;
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.set(minX + maxX, minY + maxY, minZ + maxZ);
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.multLocal(0.5f);
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = maxX - center.x;
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = maxY - center.y;
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = maxZ - center.z;
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>transform</code> modifies the center of the box to reflect the
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * change made via a rotation, translation and scale.
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param trans
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the transform to apply
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param store
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            box to store result in
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingVolume transform(Transform trans, BoundingVolume store) {
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        BoundingBox box;
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null || store.getType() != Type.AABB) {
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            box = new BoundingBox();
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            box = (BoundingBox) store;
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.mult(trans.getScale(), box.center);
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        trans.getRotation().mult(box.center, box.center);
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.center.addLocal(trans.getTranslation());
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Matrix3f transMatrix = vars.tempMat3;
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        transMatrix.set(trans.getRotation());
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Make the rotation matrix all positive to get the maximum x/y/z extent
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        transMatrix.absoluteLocal();
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f scale = trans.getScale();
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect1.set(xExtent * scale.x, yExtent * scale.y, zExtent * scale.z);
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        transMatrix.mult(vars.vect1, vars.vect2);
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Assign the biggest rotations after scales.
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.xExtent = FastMath.abs(vars.vect2.getX());
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.yExtent = FastMath.abs(vars.vect2.getY());
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.zExtent = FastMath.abs(vars.vect2.getZ());
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return box;
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingVolume transform(Matrix4f trans, BoundingVolume store) {
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        BoundingBox box;
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null || store.getType() != Type.AABB) {
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            box = new BoundingBox();
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            box = (BoundingBox) store;
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float w = trans.multProj(center, box.center);
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.center.divideLocal(w);
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Matrix3f transMatrix = vars.tempMat3;
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        trans.toRotationMatrix(transMatrix);
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Make the rotation matrix all positive to get the maximum x/y/z extent
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        transMatrix.absoluteLocal();
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect1.set(xExtent, yExtent, zExtent);
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        transMatrix.mult(vars.vect1, vars.vect1);
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Assign the biggest rotations after scales.
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.xExtent = FastMath.abs(vars.vect1.getX());
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.yExtent = FastMath.abs(vars.vect1.getY());
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        box.zExtent = FastMath.abs(vars.vect1.getZ());
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return box;
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>whichSide</code> takes a plane (typically provided by a view
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * frustum) to determine which side this bound is on.
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param plane
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the plane to check against.
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Plane.Side whichSide(Plane plane) {
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float radius = FastMath.abs(xExtent * plane.getNormal().getX())
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + FastMath.abs(yExtent * plane.getNormal().getY())
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + FastMath.abs(zExtent * plane.getNormal().getZ());
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float distance = plane.pseudoDistance(center);
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //changed to < and > to prevent floating point precision problems
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (distance < -radius) {
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return Plane.Side.Negative;
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (distance > radius) {
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return Plane.Side.Positive;
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return Plane.Side.None;
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>merge</code> combines this sphere with a second bounding sphere.
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This new sphere contains both bounding spheres and is returned.
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param volume
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the sphere to combine with this sphere.
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the new sphere
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingVolume merge(BoundingVolume volume) {
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (volume == null) {
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return this;
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (volume.getType()) {
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case AABB: {
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                BoundingBox vBox = (BoundingBox) volume;
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return merge(vBox.center, vBox.xExtent, vBox.yExtent,
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vBox.zExtent, new BoundingBox(new Vector3f(0, 0, 0), 0,
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0, 0));
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Sphere: {
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                BoundingSphere vSphere = (BoundingSphere) volume;
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return merge(vSphere.center, vSphere.radius, vSphere.radius,
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vSphere.radius, new BoundingBox(new Vector3f(0, 0, 0),
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0, 0, 0));
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case OBB: {
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                OrientedBoundingBox box = (OrientedBoundingBox) volume;
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                BoundingBox rVal = (BoundingBox) this.clone(null);
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return rVal.mergeOBB(box);
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return null;
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>mergeLocal</code> combines this sphere with a second bounding
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * sphere locally. Altering this sphere to contain both the original and the
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * additional sphere volumes;
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param volume
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the sphere to combine with this sphere.
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return this
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingVolume mergeLocal(BoundingVolume volume) {
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (volume == null) {
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return this;
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (volume.getType()) {
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case AABB: {
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                BoundingBox vBox = (BoundingBox) volume;
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return merge(vBox.center, vBox.xExtent, vBox.yExtent,
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vBox.zExtent, this);
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Sphere: {
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                BoundingSphere vSphere = (BoundingSphere) volume;
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return merge(vSphere.center, vSphere.radius, vSphere.radius,
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vSphere.radius, this);
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case OBB: {
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return mergeOBB((OrientedBoundingBox) volume);
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return null;
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Merges this AABB with the given OBB.
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param volume
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the OBB to merge this AABB with.
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return This AABB extended to fit the given OBB.
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private BoundingBox mergeOBB(OrientedBoundingBox volume) {
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (!volume.correctCorners)
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            volume.computeCorners();
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        TempVars vars = TempVars.get();
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        Vector3f min = vars.compVect1.set(center.x - xExtent, center.y - yExtent,
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                center.z - zExtent);
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        Vector3f max = vars.compVect2.set(center.x + xExtent, center.y + yExtent,
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                center.z + zExtent);
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        for (int i = 1; i < volume.vectorStore.length; i++) {
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            Vector3f temp = volume.vectorStore[i];
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (temp.x < min.x)
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                min.x = temp.x;
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            else if (temp.x > max.x)
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                max.x = temp.x;
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (temp.y < min.y)
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                min.y = temp.y;
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            else if (temp.y > max.y)
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                max.y = temp.y;
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (temp.z < min.z)
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                min.z = temp.z;
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            else if (temp.z > max.z)
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                max.z = temp.z;
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        center.set(min.addLocal(max));
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        center.multLocal(0.5f);
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        xExtent = max.x - center.x;
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        yExtent = max.y - center.y;
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        zExtent = max.z - center.z;
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        return this;
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>merge</code> combines this bounding box with another box which is
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * defined by the center, x, y, z extents.
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param boxCenter
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the center of the box to merge with
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param boxX
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the x extent of the box to merge with.
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param boxY
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the y extent of the box to merge with.
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param boxZ
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the z extent of the box to merge with.
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param rVal
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the resulting merged box.
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the resulting merged box.
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private BoundingBox merge(Vector3f boxCenter, float boxX, float boxY,
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float boxZ, BoundingBox rVal) {
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect1.x = center.x - xExtent;
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect1.x > boxCenter.x - boxX) {
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect1.x = boxCenter.x - boxX;
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect1.y = center.y - yExtent;
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect1.y > boxCenter.y - boxY) {
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect1.y = boxCenter.y - boxY;
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect1.z = center.z - zExtent;
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect1.z > boxCenter.z - boxZ) {
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect1.z = boxCenter.z - boxZ;
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect2.x = center.x + xExtent;
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect2.x < boxCenter.x + boxX) {
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect2.x = boxCenter.x + boxX;
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect2.y = center.y + yExtent;
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect2.y < boxCenter.y + boxY) {
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect2.y = boxCenter.y + boxY;
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.vect2.z = center.z + zExtent;
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vars.vect2.z < boxCenter.z + boxZ) {
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.vect2.z = boxCenter.z + boxZ;
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        center.set(vars.vect2).addLocal(vars.vect1).multLocal(0.5f);
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = vars.vect2.x - center.x;
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = vars.vect2.y - center.y;
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = vars.vect2.z - center.z;
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rVal;
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>clone</code> creates a new BoundingBox object containing the same
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * data as this one.
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param store
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            where to store the cloned information. if null or wrong class,
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            a new store is created.
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the new BoundingBox
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BoundingVolume clone(BoundingVolume store) {
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store != null && store.getType() == Type.AABB) {
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            BoundingBox rVal = (BoundingBox) store;
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rVal.center.set(center);
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rVal.xExtent = xExtent;
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rVal.yExtent = yExtent;
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rVal.zExtent = zExtent;
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rVal.checkPlane = checkPlane;
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return rVal;
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        BoundingBox rVal = new BoundingBox(center.clone(),
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                xExtent, yExtent, zExtent);
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rVal;
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>toString</code> returns the string representation of this object.
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The form is: "Radius: RRR.SSSS Center: <Vector>".
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the string representation of this.
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public String toString() {
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return getClass().getSimpleName() + " [Center: " + center + "  xExtent: "
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + xExtent + "  yExtent: " + yExtent + "  zExtent: " + zExtent
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + "]";
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * intersects determines if this Bounding Box intersects with another given
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * bounding volume. If so, true is returned, otherwise, false is returned.
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see BoundingVolume#intersects(com.jme3.bounding.BoundingVolume)
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersects(BoundingVolume bv) {
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return bv.intersectsBoundingBox(this);
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * determines if this bounding box intersects a given bounding sphere.
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere)
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersectsSphere(BoundingSphere bs) {
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (FastMath.abs(center.x - bs.center.x) < bs.getRadius()
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + xExtent
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.y - bs.center.y) < bs.getRadius()
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + yExtent
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.z - bs.center.z) < bs.getRadius()
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + zExtent) {
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return true;
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return false;
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * determines if this bounding box intersects a given bounding box. If the
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * two boxes intersect in any way, true is returned. Otherwise, false is
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * returned.
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see BoundingVolume#intersectsBoundingBox(com.jme3.bounding.BoundingBox)
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersectsBoundingBox(BoundingBox bb) {
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (center.x + xExtent < bb.center.x - bb.xExtent
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || center.x - xExtent > bb.center.x + bb.xExtent) {
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (center.y + yExtent < bb.center.y - bb.yExtent
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || center.y - yExtent > bb.center.y + bb.yExtent) {
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (center.z + zExtent < bb.center.z - bb.zExtent
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || center.z - zExtent > bb.center.z + bb.zExtent) {
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return true;
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * determines if this bounding box intersects with a given oriented bounding
62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * box.
63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see com.jme.bounding.BoundingVolume#intersectsOrientedBoundingBox(com.jme.bounding.OrientedBoundingBox)
63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    public boolean intersectsOrientedBoundingBox(OrientedBoundingBox obb) {
63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        return obb.intersectsBoundingBox(this);
63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * determines if this bounding box intersects with a given ray object. If an
63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * intersection has occurred, true is returned, otherwise false is returned.
63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see BoundingVolume#intersects(com.jme3.math.Ray)
64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersects(Ray ray) {
64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert Vector3f.isValidVector(center);
64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float rhs;
64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f diff = ray.origin.subtract(getCenter(vars.vect2), vars.vect1);
65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        final float[] fWdU = vars.fWdU;
65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        final float[] fAWdU = vars.fAWdU;
65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        final float[] fDdU = vars.fDdU;
65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        final float[] fADdU = vars.fADdU;
65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        final float[] fAWxDdU = vars.fAWxDdU;
65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fWdU[0] = ray.getDirection().dot(Vector3f.UNIT_X);
65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWdU[0] = FastMath.abs(fWdU[0]);
65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fDdU[0] = diff.dot(Vector3f.UNIT_X);
66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fADdU[0] = FastMath.abs(fDdU[0]);
66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fADdU[0] > xExtent && fDdU[0] * fWdU[0] >= 0.0) {
66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fWdU[1] = ray.getDirection().dot(Vector3f.UNIT_Y);
66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWdU[1] = FastMath.abs(fWdU[1]);
66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fDdU[1] = diff.dot(Vector3f.UNIT_Y);
66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fADdU[1] = FastMath.abs(fDdU[1]);
67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fADdU[1] > yExtent && fDdU[1] * fWdU[1] >= 0.0) {
67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fWdU[2] = ray.getDirection().dot(Vector3f.UNIT_Z);
67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWdU[2] = FastMath.abs(fWdU[2]);
67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fDdU[2] = diff.dot(Vector3f.UNIT_Z);
67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fADdU[2] = FastMath.abs(fDdU[2]);
67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fADdU[2] > zExtent && fDdU[2] * fWdU[2] >= 0.0) {
68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f wCrossD = ray.getDirection().cross(diff, vars.vect2);
68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWxDdU[0] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_X));
68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rhs = yExtent * fAWdU[2] + zExtent * fAWdU[1];
68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fAWxDdU[0] > rhs) {
68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWxDdU[1] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Y));
69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rhs = xExtent * fAWdU[2] + zExtent * fAWdU[0];
69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fAWxDdU[1] > rhs) {
69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fAWxDdU[2] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Z));
70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rhs = xExtent * fAWdU[1] + yExtent * fAWdU[0];
70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fAWxDdU[2] > rhs) {
70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vars.release();
70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return false;
70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return true;
70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see com.jme.bounding.BoundingVolume#intersectsWhere(com.jme.math.Ray)
71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int collideWithRay(Ray ray, CollisionResults results) {
71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f diff = vars.vect1.set(ray.origin).subtractLocal(center);
71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f direction = vars.vect2.set(ray.direction);
71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float[] t = {0f, Float.POSITIVE_INFINITY};
72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float saveT0 = t[0], saveT1 = t[1];
72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean notEntirelyClipped = clip(+direction.x, -diff.x - xExtent, t)
72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && clip(-direction.x, +diff.x - xExtent, t)
72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && clip(+direction.y, -diff.y - yExtent, t)
72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && clip(-direction.y, +diff.y - yExtent, t)
72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && clip(+direction.z, -diff.z - zExtent, t)
72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && clip(-direction.z, +diff.z - zExtent, t);
72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (notEntirelyClipped && (t[0] != saveT0 || t[1] != saveT1)) {
73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (t[1] > t[0]) {
73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float[] distances = t;
73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f[] points = new Vector3f[]{
73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    new Vector3f(ray.direction).multLocal(distances[0]).addLocal(ray.origin),
73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    new Vector3f(ray.direction).multLocal(distances[1]).addLocal(ray.origin)
73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                };
73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                CollisionResult result = new CollisionResult(points[0], distances[0]);
74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                results.addCollision(result);
74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                result = new CollisionResult(points[1], distances[1]);
74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                results.addCollision(result);
74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return 2;
74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Vector3f point = new Vector3f(ray.direction).multLocal(t[0]).addLocal(ray.origin);
74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            CollisionResult result = new CollisionResult(point, t[0]);
74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            results.addCollision(result);
74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return 1;
75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return 0;
75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int collideWith(Collidable other, CollisionResults results) {
75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (other instanceof Ray) {
75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Ray ray = (Ray) other;
75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return collideWithRay(ray, results);
75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (other instanceof Triangle) {
75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Triangle t = (Triangle) other;
76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (intersects(t.get1(), t.get2(), t.get3())) {
76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                CollisionResult r = new CollisionResult();
76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                results.addCollision(r);
76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return 1;
76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return 0;
76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * C code ported from <a href="http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt">
77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt</a>
77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param v1 The first point in the triangle
77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param v2 The second point in the triangle
77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param v3 The third point in the triangle
77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return True if the bounding box intersects the triangle, false
77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * otherwise.
78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersects(Vector3f v1, Vector3f v2, Vector3f v3) {
78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return Intersection.intersect(this, v1, v2, v3);
78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean contains(Vector3f point) {
78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.abs(center.x - point.x) < xExtent
78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.y - point.y) < yExtent
78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.z - point.z) < zExtent;
79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean intersects(Vector3f point) {
79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.abs(center.x - point.x) <= xExtent
79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.y - point.y) <= yExtent
79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                && FastMath.abs(center.z - point.z) <= zExtent;
79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distanceToEdge(Vector3f point) {
80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // compute coordinates of point in box coordinate system
80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars= TempVars.get();
80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f closest = vars.vect1;
80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        point.subtract(center,closest);
80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // project test point onto box
80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float sqrDistance = 0.0f;
80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float delta;
80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (closest.x < -xExtent) {
81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.x + xExtent;
81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.x = -xExtent;
81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (closest.x > xExtent) {
81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.x - xExtent;
81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.x = xExtent;
81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (closest.y < -yExtent) {
82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.y + yExtent;
82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.y = -yExtent;
82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (closest.y > yExtent) {
82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.y - yExtent;
82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.y = yExtent;
82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (closest.z < -zExtent) {
83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.z + zExtent;
83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.z = -zExtent;
83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (closest.z > zExtent) {
83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            delta = closest.z - zExtent;
83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sqrDistance += delta * delta;
83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            closest.z = zExtent;
83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return FastMath.sqrt(sqrDistance);
84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>clip</code> determines if a line segment intersects the current
84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * test plane.
84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param denom
84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the denominator of the line segment.
85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param numer
85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the numerator of the line segment.
85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param t
85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            test values of the plane.
85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return true if the line segment intersects the plane, false otherwise.
85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean clip(float denom, float numer, float[] t) {
85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Return value is 'true' if line segment intersects the current test
85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // plane. Otherwise 'false' is returned in which case the line segment
85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // is entirely clipped.
86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (denom > 0.0f) {
86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (numer > denom * t[1]) {
86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return false;
86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (numer > denom * t[0]) {
86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                t[0] = numer / denom;
86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return true;
86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (denom < 0.0f) {
86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (numer > denom * t[0]) {
87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return false;
87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (numer > denom * t[1]) {
87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                t[1] = numer / denom;
87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return true;
87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return numer <= 0.0;
87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Query extent.
88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param store
88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            where extent gets stored - null to return a new vector
88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return store / new vector
88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getExtent(Vector3f store) {
88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.set(xExtent, yExtent, zExtent);
89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return store;
89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getXExtent() {
89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return xExtent;
89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getYExtent() {
90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return yExtent;
90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getZExtent() {
90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return zExtent;
90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setXExtent(float xExtent) {
90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (xExtent < 0) {
91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException();
91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.xExtent = xExtent;
91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setYExtent(float yExtent) {
91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (yExtent < 0) {
91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException();
91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.yExtent = yExtent;
92259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
92359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setZExtent(float zExtent) {
92559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (zExtent < 0) {
92659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException();
92759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
92859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.zExtent = zExtent;
93059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
93159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
93259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getMin(Vector3f store) {
93359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
93459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
93559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
93659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.set(center).subtractLocal(xExtent, yExtent, zExtent);
93759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return store;
93859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
93959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
94059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getMax(Vector3f store) {
94159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
94259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
94359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
94459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.set(center).addLocal(xExtent, yExtent, zExtent);
94559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return store;
94659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
94759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
94859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setMinMax(Vector3f min, Vector3f max) {
94959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.center.set(max).addLocal(min).multLocal(0.5f);
95059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = FastMath.abs(max.x - center.x);
95159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = FastMath.abs(max.y - center.y);
95259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = FastMath.abs(max.z - center.z);
95359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
95459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
95559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
95659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter e) throws IOException {
95759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.write(e);
95859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule capsule = e.getCapsule(this);
95959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(xExtent, "xExtent", 0);
96059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(yExtent, "yExtent", 0);
96159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(zExtent, "zExtent", 0);
96259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
96359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
96459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
96559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter e) throws IOException {
96659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.read(e);
96759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule capsule = e.getCapsule(this);
96859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        xExtent = capsule.readFloat("xExtent", 0);
96959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        yExtent = capsule.readFloat("yExtent", 0);
97059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        zExtent = capsule.readFloat("zExtent", 0);
97159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
97259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
97359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
97459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getVolume() {
97559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return (8 * xExtent * yExtent * zExtent);
97659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
97759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
978