📄 boundingsphere.java
字号:
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 + -