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

📄 boundingsphere.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    private float getMaxAxis(Vector3f scale) {
        float x = FastMath.abs(scale.x);
        float y = FastMath.abs(scale.y);
        float z = FastMath.abs(scale.z);
        
        if (x >= y) {
            if (x >= z)
                return x;
            return z;
        }
        
        if (y >= z)
            return y;
        
        return z;
    }

    /**
     * <code>whichSide</code> takes a plane (typically provided by a view
     * frustum) to determine which side this bound is on.
     *
     * @param plane
     *            the plane to check against.
     * @return side
     */
    public Side whichSide(Plane plane) {
        float distance = plane.pseudoDistance(center);
        if (distance <= -radius) { return Side.NEGATIVE; }
        if (distance >=  radius) { return Side.POSITIVE; }
        return Side.NONE;
    }

    /**
     * <code>merge</code> combines this sphere with a second bounding sphere.
     * This new sphere contains both bounding spheres and is returned.
     *
     * @param volume
     *            the sphere to combine with this sphere.
     * @return a new sphere
     */
    public BoundingVolume merge(BoundingVolume volume) {
        if (volume == null) {
            return this;
        }

        switch(volume.getType()) {

        case Sphere: {
        	BoundingSphere sphere = (BoundingSphere) volume;
            float temp_radius = sphere.getRadius();
            Vector3f temp_center = sphere.getCenter();
            BoundingSphere rVal = new BoundingSphere();
            return merge(temp_radius, temp_center, rVal);
        }
        
        case Capsule: {
        	BoundingCapsule capsule = (BoundingCapsule) volume;
            float temp_radius = capsule.getRadius() 
            	+ capsule.getLineSegment().getExtent();
            Vector3f temp_center = capsule.getCenter();
            BoundingSphere rVal = new BoundingSphere();
            return merge(temp_radius, temp_center, rVal);
        }

        case AABB: {
        	BoundingBox box = (BoundingBox) volume;
            Vector3f radVect = new Vector3f(box.xExtent, box.yExtent,
                    box.zExtent);
            Vector3f temp_center = box.center;
            BoundingSphere rVal = new BoundingSphere();
            return merge(radVect.length(), temp_center, rVal);
        }

        case OBB: {
        	OrientedBoundingBox box = (OrientedBoundingBox) volume;
            BoundingSphere rVal = (BoundingSphere) this.clone(null);
            return rVal.mergeOBB(box);
        }

        default:
        	return null;

        }
    }

    private Vector3f tmpRadVect = new Vector3f();

    /**
     * <code>mergeLocal</code> combines this sphere with a second bounding
     * sphere locally. Altering this sphere to contain both the original and the
     * additional sphere volumes;
     *
     * @param volume
     *            the sphere to combine with this sphere.
     * @return this
     */
    public BoundingVolume mergeLocal(BoundingVolume volume) {
        if (volume == null) {
            return this;
        }

        switch (volume.getType()) {

        case Sphere: {
        	BoundingSphere sphere = (BoundingSphere) volume;
            float temp_radius = sphere.getRadius();
            Vector3f temp_center = sphere.getCenter();
            return merge(temp_radius, temp_center, this);
        }

        case AABB: {
        	BoundingBox box = (BoundingBox) volume;
            Vector3f radVect = tmpRadVect;
            radVect.set(box.xExtent, box.yExtent, box.zExtent);
            Vector3f temp_center = box.center;
            return merge(radVect.length(), temp_center, this);
        }

        case OBB: {
        	return mergeOBB((OrientedBoundingBox) volume);
        }
        
        case Capsule: {
        	BoundingCapsule capsule = (BoundingCapsule) volume;
        	return merge(capsule.getRadius() + capsule.getLineSegment().getExtent(), 
        			capsule.getCenter(), this);
        }

        default:
        	return null;
        }
    }

    /**
     * Merges this sphere with the given OBB.
     *
     * @param volume
     *            The OBB to merge.
     * @return This sphere, after merging.
     */
    private BoundingSphere mergeOBB(OrientedBoundingBox volume) {
        // compute edge points from the obb
        if (!volume.correctCorners)
            volume.computeCorners();
        _mergeBuf.rewind();
        for (int i = 0; i < 8; i++) {
            _mergeBuf.put(volume.vectorStore[i].x);
            _mergeBuf.put(volume.vectorStore[i].y);
            _mergeBuf.put(volume.vectorStore[i].z);
        }

        // remember old radius and center
        float oldRadius = radius;
        Vector3f oldCenter = _compVect2.set( center );

        // compute new radius and center from obb points
        computeFromPoints(_mergeBuf);
        Vector3f newCenter = _compVect3.set( center );
        float newRadius = radius;

        // restore old center and radius
        center.set( oldCenter );
        radius = oldRadius;

        //merge obb points result
        merge( newRadius, newCenter, this );

        return this;
    }

    private BoundingVolume merge(float temp_radius, Vector3f temp_center,
            BoundingSphere rVal) {
        Vector3f diff = temp_center.subtract(center, _compVect1);
        float lengthSquared = diff.lengthSquared();
        float radiusDiff = temp_radius - radius;

        float fRDiffSqr = radiusDiff * radiusDiff;

        if (fRDiffSqr >= lengthSquared) {
            if (radiusDiff <= 0.0f) {
                return this;
            } 
                
            Vector3f rCenter = rVal.getCenter();
            if ( rCenter == null ) {
                rVal.setCenter( rCenter = new Vector3f() );
            }
            rCenter.set(temp_center);
            rVal.setRadius(temp_radius);
            return rVal;
        }

        float length = (float) Math.sqrt(lengthSquared);

        Vector3f rCenter = rVal.getCenter();
        if ( rCenter == null ) {
            rVal.setCenter( rCenter = new Vector3f() );
        }
        if (length > radiusEpsilon) {
            float coeff = (length + radiusDiff) / (2.0f * length);
            rCenter.set(center.addLocal(diff.multLocal(coeff)));
        } else {
            rCenter.set(center);
        }

        rVal.setRadius(0.5f * (length + radius + temp_radius));
        return rVal;
    }

    /**
     * <code>clone</code> creates a new BoundingSphere object containing the
     * same data as this one.
     *
     * @param store
     *            where to store the cloned information. if null or wrong class,
     *            a new store is created.
     * @return the new BoundingSphere
     */
    public BoundingVolume clone(BoundingVolume store) {
        if (store != null && store.getType() == Type.Sphere) {
            BoundingSphere rVal = (BoundingSphere) store;
            if (null == rVal.center) {
                rVal.center = new Vector3f();
            }
            rVal.center.set(center);
            rVal.radius = radius;
            rVal.checkPlane = checkPlane;
            return rVal;
        } 
        
        return new BoundingSphere(radius,
                    (center != null ? (Vector3f) center.clone() : null));
    }

    /**
     * <code>toString</code> returns the string representation of this object.
     * The form is: "Radius: RRR.SSSS Center: <Vector>".
     *
     * @return the string representation of this.
     */
    public String toString() {
        return "com.jme.scene.BoundingSphere [Radius: " + radius + " Center: "
                + center + "]";
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersects(com.jme.bounding.BoundingVolume)
     */
    public boolean intersects(BoundingVolume bv) {
        if (bv == null)
            return false;
        
        return bv.intersectsSphere(this);
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere)
     */
    public boolean intersectsSphere(BoundingSphere bs) {
        if (!Vector3f.isValidVector(center) || !Vector3f.isValidVector(bs.center)) return false;

        Vector3f diff = getCenter().subtract(bs.getCenter(), _compVect1);
        float rsum = getRadius() + bs.getRadius();
        return (diff.dot(diff) <= rsum * rsum);
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox)
     */
    public boolean intersectsBoundingBox(BoundingBox bb) {
        if (!Vector3f.isValidVector(center) || !Vector3f.isValidVector(bb.center)) return false;

        if (FastMath.abs(bb.center.x - getCenter().x) < getRadius()
                + bb.xExtent
                && FastMath.abs(bb.center.y - getCenter().y) < getRadius()
                        + bb.yExtent
                && FastMath.abs(bb.center.z - getCenter().z) < getRadius()
                        + bb.zExtent)
            return true;

        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersectsOrientedBoundingBox(com.jme.bounding.OrientedBoundingBox)
     */
    public boolean intersectsOrientedBoundingBox(OrientedBoundingBox obb) {
        return obb.intersectsSphere(this);
    }
    
    public boolean intersectsCapsule(BoundingCapsule bc) {
    	return bc.intersectsSphere(this);
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersects(com.jme.math.Ray)
     */
    public boolean intersects(Ray ray) {
        if (!Vector3f.isValidVector(center)) return false;

        Vector3f diff = _compVect1.set(ray.getOrigin())
                .subtractLocal(getCenter());
        float radiusSquared = getRadius() * getRadius();
        float a = diff.dot(diff) - radiusSquared;
        if (a <= 0.0) {
            // in sphere
            return true;
        }

        // outside sphere
        float b = ray.getDirection().dot(diff);
        if (b >= 0.0) {
            return false;
        }
        return b*b >= a;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.jme.bounding.BoundingVolume#intersectsWhere(com.jme.math.Ray)
     */
    public IntersectionRecord intersectsWhere(Ray ray) {
        Vector3f diff = _compVect1.set(ray.getOrigin()).subtractLocal(
                getCenter());
        float a = diff.dot(diff) - (getRadius()*getRadius());
        float a1, discr, root;
        if (a <= 0.0) {
            // inside sphere
            a1 = ray.direction.dot(diff);
            discr = (a1 * a1) - a;
            root = FastMath.sqrt(discr);
            float[] distances = new float[] { root - a1 };
            Vector3f[] points = new Vector3f[] { new Vector3f(ray.direction)
                    .multLocal(distances[0]).addLocal(ray.origin) };
            IntersectionRecord record = new IntersectionRecord(distances, points);
            return record;
        }
        
        a1 = ray.direction.dot(diff);
        if (a1 >= 0.0) {
            return new IntersectionRecord();
        }
        
        discr = a1*a1 - a;
        if (discr < 0.0)
            return new IntersectionRecord();
        else if (discr >= FastMath.ZERO_TOLERANCE) {
            root = FastMath.sqrt(discr);
            float[] distances = new float[] { -a1 - root, -a1 + root };
            Vector3f[] points = new Vector3f[] { 
                    new Vector3f(ray.direction).multLocal(distances[0]).addLocal(ray.origin),
                    new Vector3f(ray.direction).multLocal(distances[1]).addLocal(ray.origin)
                    };
            IntersectionRecord record = new IntersectionRecord(distances, points);
            return record;
        } else {
            float[] distances = new float[] { -a1 };
            Vector3f[] points = new Vector3f[] { 
                    new Vector3f(ray.direction).multLocal(distances[0]).addLocal(ray.origin) 
                    };
            IntersectionRecord record = new IntersectionRecord(distances, points);
            return record;
        }
    }

    @Override
    public boolean contains(Vector3f point) {
        return getCenter().distanceSquared(point) < (getRadius() * getRadius());
    }

    public float distanceToEdge(Vector3f point) {
        return center.distance(point) - radius;
    }
    
    public void write(JMEExporter e) throws IOException {
        super.write(e);
        try {
            e.getCapsule(this).write(radius, "radius", 0);
        } catch (IOException ex) {
            logger.logp(Level.SEVERE, this.getClass().toString(), "write(JMEExporter)", "Exception", ex);
        }
    }

    public void read(JMEImporter e) throws IOException {
        super.read(e);
        try {
            radius = e.getCapsule(this).readFloat("radius", 0);
        } catch (IOException ex) {
            logger.logp(Level.SEVERE, this.getClass().toString(), "read(JMEImporter)", "Exception", ex);
        }
    }

    @Override
    public float getVolume() {
        return 4 * FastMath.ONE_THIRD * FastMath.PI * radius * radius * radius;
    }
}

⌨️ 快捷键说明

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