package com.jme.bounding; import com.jme.math.*; import com.jme.scene.*; import DPJRuntime.*; /* * Copyright (c) 2003-2008 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'jMonkeyEngine' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * <code>BoundingBox</code> defines an axis-aligned cube that defines a * container for a group of vertices of a particular piece of geometry. This box * defines a center and extents from that center along the x, y and z axis. <br> * <br> * A typical usage is to allow the class define the center and radius by calling * either <code>containAABB</code> or <code>averagePoints</code>. A call to * <code>computeFramePoint</code> in turn calls <code>containAABB</code>. * * @author Joshua Slack * @version $Id: BoundingBox.java,v 1.50 2007/09/22 16:46:35 irrisor Exp $ */ public class BoundingBox<region R> extends BoundingVolume<R> { public float xExtent in R, yExtent in R, zExtent in R; /** * Default constructor instantiates a new <code>BoundingBox</code> * object. */ public BoundingBox() { } /** * Contstructor instantiates a new <code>BoundingBox</code> object with * given specs. */ public <region Rc> BoundingBox(Vector3f<Rc> c, float x, float y, float z) reads Rc writes R { this.center.set(c); this.xExtent = x; this.yExtent = y; this.zExtent = z; } /** * Region-aware copy constructor */ public BoundingBox(BoundingBox<*> bb) { this.xExtent = bb.xExtent; this.yExtent = bb.yExtent; this.zExtent = bb.zExtent; if (bb.center != null) { this.center.x = bb.center.x; this.center.y = bb.center.y; this.center.z = bb.center.z; } } public <region Rindices> void computeFromTris(ArrayInt<Rindices> indices, TriMesh<Rindices> mesh, int start, int end) { if (end - start <= 0) { return; } Vector3f min = new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); Vector3f max = new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); Vector3f point; Vector3f.Array verts = new Vector3f.Array(3); for (int i = start; i < end; i++) { mesh.<region Root>getTriangle(indices[i], verts); point = verts[0]; checkMinMax(min, max, point); point = verts[1]; checkMinMax(min, max, point); point = verts[2]; checkMinMax(min, max, point); } center.set(min.addLocal(max)); center.multLocal(0.5f); xExtent = max.x - center.x; yExtent = max.y - center.y; zExtent = max.z - center.z; } private void checkMinMax(Vector3f min, Vector3f max, Vector3f point) { if (point.x < min.x) min.x = point.x; else if (point.x > max.x) max.x = point.x; if (point.y < min.y) min.y = point.y; else if (point.y > max.y) max.y = point.y; if (point.z < min.z) min.z = point.z; else if (point.z > max.z) max.z = point.z; } /** * <code>transform</code> modifies the center of the box to reflect the * change made via a rotation, translation and scale. * * @param rotate * the rotation change. * @param translate * the translation change. * @param scale * the size change. * @param store * box to store result in */ public <region Rrotate, Rtranslate, Rscale, Rstore, RTemp1, RTemp2, RTemp3> BoundingBox<Rstore> transform_r(Quaternion<Rrotate> rotate, Vector3f<Rtranslate> translate, Vector3f<Rscale> scale, BoundingBox<Rstore> store, Matrix3f<RTemp1> _compMat, Vector3f<RTemp2> _compVect1, Vector3f<RTemp3> _compVect2) reads R, Rrotate, Rtranslate, Rscale writes RTemp1, RTemp2, RTemp3, Rstore { BoundingBox<Rstore> box; if (store == null) { box = new BoundingBox<Rstore>(); } else { box = store; } BoundingVolume<Rstore> boxVol = box; center.mult(scale, boxVol.center); rotate.mult(boxVol.center, boxVol.center); boxVol.center.addLocal(translate); Matrix3f<RTemp1> transMatrix = _compMat; transMatrix.set(rotate); // Make the rotation matrix all positive to get the maximum x/y/z extent transMatrix.m00 = Math.abs(transMatrix.m00); transMatrix.m01 = Math.abs(transMatrix.m01); transMatrix.m02 = Math.abs(transMatrix.m02); transMatrix.m10 = Math.abs(transMatrix.m10); transMatrix.m11 = Math.abs(transMatrix.m11); transMatrix.m12 = Math.abs(transMatrix.m12); transMatrix.m20 = Math.abs(transMatrix.m20); transMatrix.m21 = Math.abs(transMatrix.m21); transMatrix.m22 = Math.abs(transMatrix.m22); _compVect1.set(xExtent * scale.x, yExtent * scale.y, zExtent * scale.z); transMatrix.mult(_compVect1, _compVect2); // Assign the biggest rotations after scales. box.xExtent = Math.abs(_compVect2.x); box.yExtent = Math.abs(_compVect2.y); box.zExtent = Math.abs(_compVect2.z); return box; } /** * determines if this bounding box intersects a given bounding box. If the * two boxes intersect in any way, true is returned. Otherwise, false is * returned. * * @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox) */ public <region Rbb> boolean intersectsBoundingBox(BoundingBox<Rbb> bb) reads R, Rbb { BoundingVolume<Rbb> bbVol = bb; if (!Vector3f.isValidVector(center) || !Vector3f.isValidVector(bbVol.center)) return false; if (center.x + xExtent < bbVol.center.x - bb.xExtent || center.x - xExtent > bbVol.center.x + bb.xExtent) { return false; } else if (center.y + yExtent < bbVol.center.y - bb.yExtent || center.y - yExtent > bbVol.center.y + bb.yExtent) { return false; } else if (center.z + zExtent < bbVol.center.z - bb.zExtent || center.z - zExtent > bbVol.center.z + bb.zExtent) { return false; } else return true; } }