⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 orientedboundingbox.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 2003-2009 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.
 */

package com.jme.bounding;

import java.io.IOException;
import java.nio.FloatBuffer;

import com.jme.intersection.IntersectionRecord;
import com.jme.math.FastMath;
import com.jme.math.Matrix3f;
import com.jme.math.Plane;
import com.jme.math.Quaternion;
import com.jme.math.Ray;
import com.jme.math.Triangle;
import com.jme.math.Vector3f;
import com.jme.math.Plane.Side;
import com.jme.scene.TriMesh;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;
import com.jme.util.geom.BufferUtils;

/**
 * Started Date: Sep 5, 2004 <br>
 * <br>
 * 
 * @author Jack Lindamood
 * @author Joshua Slack (alterations for .9)
 * @version $Id: OrientedBoundingBox.java,v 1.35 2007/09/21 15:45:31 nca Exp $
 */
public class OrientedBoundingBox extends BoundingVolume {

    private static final long serialVersionUID = 1L;

    // TODO: Really need to move from static compute fields to an object pool.
    static private final Vector3f _compVect3 = new Vector3f();

    static private final Vector3f _compVect4 = new Vector3f();

    static private final Vector3f _compVect5 = new Vector3f();

    static private final Vector3f _compVect6 = new Vector3f();

    static private final Vector3f _compVect7 = new Vector3f();

    static private final Vector3f _compVect8 = new Vector3f();

    static private final Vector3f _compVect9 = new Vector3f();

    static private final Vector3f _compVect10 = new Vector3f();

    static private final Vector3f tempVe = new Vector3f();

    static private final Matrix3f tempMa = new Matrix3f();

    static private final Quaternion tempQa = new Quaternion();

    static private final Quaternion tempQb = new Quaternion();

    private static final float[] fWdU = new float[3];

    private static final float[] fAWdU = new float[3];

    private static final float[] fDdU = new float[3];

    private static final float[] fADdU = new float[3];

    private static final float[] fAWxDdU = new float[3];

    private static final float[] tempFa = new float[3];

    private static final float[] tempFb = new float[3];

    /** X axis of the Oriented Box. */
    public final Vector3f xAxis = new Vector3f(1, 0, 0);

    /** Y axis of the Oriented Box. */
    public final Vector3f yAxis = new Vector3f(0, 1, 0);

    /** Z axis of the Oriented Box. */
    public final Vector3f zAxis = new Vector3f(0, 0, 1);

    /** Extents of the box along the x,y,z axis. */
    public final Vector3f extent = new Vector3f(0, 0, 0);

    /** Vector array used to store the array of 8 corners the box has. */
    public final Vector3f[] vectorStore = new Vector3f[8];

    private final Vector3f tempVk = new Vector3f();
    private final Vector3f tempForword = new Vector3f(0, 0, 1);
    private final Vector3f tempLeft = new Vector3f(1, 0, 0);
    private final Vector3f tempUp = new Vector3f(0, 1, 0);

    static private final FloatBuffer _mergeBuf = BufferUtils
            .createVector3Buffer(16);

    /**
     * If true, the box's vectorStore array correctly represents the box's
     * corners.
     */
    public boolean correctCorners = false;

    public OrientedBoundingBox() {
        for (int x = 0; x < 8; x++)
            vectorStore[x] = new Vector3f();
    }

    public Type getType() {
        return Type.OBB;
    }

    public BoundingVolume transform(Quaternion rotate, Vector3f translate,
            Vector3f scale, BoundingVolume store) {
        rotate.toRotationMatrix(tempMa);
        return transform(tempMa, translate, scale, store);
    }

    public BoundingVolume transform(Matrix3f rotate, Vector3f translate,
            Vector3f scale, BoundingVolume store) {
        if (store == null || store.getType() != Type.OBB) {
            store = new OrientedBoundingBox();
        }
        OrientedBoundingBox toReturn = (OrientedBoundingBox) store;
        toReturn.extent.set(FastMath.abs(extent.x * scale.x), 
                FastMath.abs(extent.y * scale.y), 
                FastMath.abs(extent.z * scale.z));
        rotate.mult(xAxis, toReturn.xAxis);
        rotate.mult(yAxis, toReturn.yAxis);
        rotate.mult(zAxis, toReturn.zAxis);
        center.mult(scale, toReturn.center);
        rotate.mult(toReturn.center, toReturn.center);
        toReturn.center.addLocal(translate);
        toReturn.correctCorners = false;
        return toReturn;
    }

    public Side whichSide(Plane plane) {
        float fRadius = FastMath.abs(extent.x * (plane.getNormal().dot(xAxis)))
                + FastMath.abs(extent.y * (plane.getNormal().dot(yAxis)))
                + FastMath.abs(extent.z * (plane.getNormal().dot(zAxis)));
        float fDistance = plane.pseudoDistance(center);
        if (fDistance <= -fRadius) { return Side.NEGATIVE; }
        if (fDistance >=  fRadius) { return Side.POSITIVE; }
        return Side.NONE;
    }

    public void computeFromPoints(FloatBuffer points) {
        containAABB(points);
    }

    /**
     * Calculates an AABB of the given point values for this OBB.
     * 
     * @param points
     *            The points this OBB should contain.
     */
    private void containAABB(FloatBuffer points) {
        if (points == null || points.limit() <= 2) { // we need at least a 3
            // float vector
            return;
        }

        BufferUtils.populateFromBuffer(_compVect1, points, 0);
        float minX = _compVect1.x, minY = _compVect1.y, minZ = _compVect1.z;
        float maxX = _compVect1.x, maxY = _compVect1.y, maxZ = _compVect1.z;

        for (int i = 1, len = points.limit() / 3; i < len; i++) {
            BufferUtils.populateFromBuffer(_compVect1, points, i);

            if (_compVect1.x < minX)
                minX = _compVect1.x;
            else if (_compVect1.x > maxX)
                maxX = _compVect1.x;

            if (_compVect1.y < minY)
                minY = _compVect1.y;
            else if (_compVect1.y > maxY)
                maxY = _compVect1.y;

            if (_compVect1.z < minZ)
                minZ = _compVect1.z;
            else if (_compVect1.z > maxZ)
                maxZ = _compVect1.z;
        }

        center.set(minX + maxX, minY + maxY, minZ + maxZ);
        center.multLocal(0.5f);

        extent.set(maxX - center.x, maxY - center.y, maxZ - center.z);

        xAxis.set(1, 0, 0);
        yAxis.set(0, 1, 0);
        zAxis.set(0, 0, 1);
        
        correctCorners = false;
    }

    public BoundingVolume merge(BoundingVolume volume) {
        // clone ourselves into a new bounding volume, then merge.
        return clone(new OrientedBoundingBox()).mergeLocal(volume);
    }

    public BoundingVolume mergeLocal(BoundingVolume volume) {
        if (volume == null)
            return this;

        switch (volume.getType()) {

            case OBB: {
                return mergeOBB((OrientedBoundingBox) volume);
            }

            case AABB: {
                return mergeAABB((BoundingBox) volume);
            }

            case Sphere: {
                return mergeSphere((BoundingSphere) volume);
            }

            default:
                return null;

        }
    }

    private BoundingVolume mergeSphere(BoundingSphere volume) {
        BoundingSphere mergeSphere = volume;
        if (!correctCorners)
            this.computeCorners();

        _mergeBuf.rewind();
        for (int i = 0; i < 8; i++) {
            _mergeBuf.put(vectorStore[i].x);
            _mergeBuf.put(vectorStore[i].y);
            _mergeBuf.put(vectorStore[i].z);
        }
        _mergeBuf.put(mergeSphere.center.x + mergeSphere.radius).put(
                mergeSphere.center.y + mergeSphere.radius).put(
                mergeSphere.center.z + mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x - mergeSphere.radius).put(
                mergeSphere.center.y + mergeSphere.radius).put(
                mergeSphere.center.z + mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x + mergeSphere.radius).put(
                mergeSphere.center.y - mergeSphere.radius).put(
                mergeSphere.center.z + mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x + mergeSphere.radius).put(
                mergeSphere.center.y + mergeSphere.radius).put(
                mergeSphere.center.z - mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x - mergeSphere.radius).put(
                mergeSphere.center.y - mergeSphere.radius).put(
                mergeSphere.center.z + mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x - mergeSphere.radius).put(
                mergeSphere.center.y + mergeSphere.radius).put(
                mergeSphere.center.z - mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x + mergeSphere.radius).put(
                mergeSphere.center.y - mergeSphere.radius).put(
                mergeSphere.center.z - mergeSphere.radius);
        _mergeBuf.put(mergeSphere.center.x - mergeSphere.radius).put(
                mergeSphere.center.y - mergeSphere.radius).put(
                mergeSphere.center.z - mergeSphere.radius);
        containAABB(_mergeBuf);
        correctCorners = false;
        return this;
    }

    private BoundingVolume mergeAABB(BoundingBox volume) {
        BoundingBox mergeBox = volume;
        if (!correctCorners)
            this.computeCorners();

        _mergeBuf.rewind();
        for (int i = 0; i < 8; i++) {
            _mergeBuf.put(vectorStore[i].x);
            _mergeBuf.put(vectorStore[i].y);
            _mergeBuf.put(vectorStore[i].z);
        }
        _mergeBuf.put(mergeBox.center.x + mergeBox.xExtent).put(
                mergeBox.center.y + mergeBox.yExtent).put(
                mergeBox.center.z + mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x - mergeBox.xExtent).put(
                mergeBox.center.y + mergeBox.yExtent).put(
                mergeBox.center.z + mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x + mergeBox.xExtent).put(
                mergeBox.center.y - mergeBox.yExtent).put(
                mergeBox.center.z + mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x + mergeBox.xExtent).put(
                mergeBox.center.y + mergeBox.yExtent).put(
                mergeBox.center.z - mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x - mergeBox.xExtent).put(
                mergeBox.center.y - mergeBox.yExtent).put(
                mergeBox.center.z + mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x - mergeBox.xExtent).put(
                mergeBox.center.y + mergeBox.yExtent).put(
                mergeBox.center.z - mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x + mergeBox.xExtent).put(
                mergeBox.center.y - mergeBox.yExtent).put(
                mergeBox.center.z - mergeBox.zExtent);
        _mergeBuf.put(mergeBox.center.x - mergeBox.xExtent).put(
                mergeBox.center.y - mergeBox.yExtent).put(
                mergeBox.center.z - mergeBox.zExtent);
        containAABB(_mergeBuf);
        correctCorners = false;
        return this;
    }

    private BoundingVolume mergeOBB(OrientedBoundingBox volume) {
        // OrientedBoundingBox mergeBox=(OrientedBoundingBox) volume;
        // if (!correctCorners) this.computeCorners();
        // if (!mergeBox.correctCorners) mergeBox.computeCorners();
        // Vector3f[] mergeArray=new Vector3f[16];
        // for (int i=0;i<vectorStore.length;i++){
        // mergeArray[i*2+0]=this .vectorStore[i];
        // mergeArray[i*2+1]=mergeBox.vectorStore[i];
        // }
        // containAABB(mergeArray);
        // correctCorners=false;
        // return this;
        // construct a box that contains the input boxes
        // Box3<Real> kBox;
        OrientedBoundingBox rkBox0 = this;
        OrientedBoundingBox rkBox1 = volume;

        // The first guess at the box center. This value will be updated later
        // after the input box vertices are projected onto axes determined by an
        // average of box axes.
        Vector3f kBoxCenter = (rkBox0.center.add(rkBox1.center, _compVect7))
                .multLocal(.5f);

        // A box's axes, when viewed as the columns of a matrix, form a rotation
        // matrix. The input box axes are converted to quaternions. The average
        // quaternion is computed, then normalized to unit length. The result is
        // the slerp of the two input quaternions with t-value of 1/2. The
        // result is converted back to a rotation matrix and its columns are
        // selected as the merged box axes.
        Quaternion kQ0 = tempQa, kQ1 = tempQb;
        kQ0.fromAxes(rkBox0.xAxis, rkBox0.yAxis, rkBox0.zAxis);
        kQ1.fromAxes(rkBox1.xAxis, rkBox1.yAxis, rkBox1.zAxis);

        if (kQ0.dot(kQ1) < 0.0f)
            kQ1.negate();

        Quaternion kQ = kQ0.addLocal(kQ1);
        kQ.normalize();

        Matrix3f kBoxaxis = kQ.toRotationMatrix(tempMa);
        Vector3f newXaxis = kBoxaxis.getColumn(0, _compVect8);
        Vector3f newYaxis = kBoxaxis.getColumn(1, _compVect9);
        Vector3f newZaxis = kBoxaxis.getColumn(2, _compVect10);

        // Project the input box vertices onto the merged-box axes. Each axis
        // D[i] containing the current center C has a minimum projected value

⌨️ 快捷键说明

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