Complete initial draft for ICollideRayVsAABB.

(Blind/untested.)
This commit is contained in:
asofold 2016-06-24 20:38:43 +02:00
parent a38e63d4a9
commit 050760afd2
3 changed files with 134 additions and 26 deletions

View File

@ -9,7 +9,7 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
private double minX, minY, minZ, maxX, maxY, maxZ; private double minX, minY, minZ, maxX, maxY, maxZ;
/** Collision or closest point. */ /** Collision or closest point. */
private double closestX, closestY, closestZ, closestTime; private double closestX, closestY, closestZ, closestDistanceSquared, closestTime;
/** /**
* Indicate a collision occurred. Reset with calling loop only. * Indicate a collision occurred. Reset with calling loop only.
*/ */
@ -59,6 +59,7 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
closestX = startX; closestX = startX;
closestY = startY; closestY = startY;
closestZ = startZ; closestZ = startZ;
closestDistanceSquared = 0.0; // Not applicable by default.
closestTime = 0.0; closestTime = 0.0;
// Determine basic orientation and timing. // Determine basic orientation and timing.
final double tMinX = CollisionUtil.getMinTimeIncludeEdges(startX, dirX, minX, maxX); final double tMinX = CollisionUtil.getMinTimeIncludeEdges(startX, dirX, minX, maxX);
@ -79,7 +80,7 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
closestZ = startZ + dirZ * tMin; closestZ = startZ + dirZ * tMin;
} }
else if (findNearestPointIfNotCollide) { else if (findNearestPointIfNotCollide) {
findNearestPoint(tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ, tMin, tMax); findNearestPoint(tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ);
} }
} }
else if (findNearestPointIfNotCollide) { else if (findNearestPointIfNotCollide) {
@ -88,28 +89,10 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
return this; return this;
} }
/**
* Find the nearest point for the case of not hitting the box, but with
* hitting min-max coordinates per axis independently.
*
* @param tMinX
* @param tMinY
* @param tMinZ
* @param tMaxX
* @param tMaxY
* @param tMaxZ
* @param tMin
* @param tMax
*/
private void findNearestPoint(final double tMinX, final double tMinY, final double tMinZ,
final double tMaxX, final double tMaxY, final double tMaxZ,
final double tMin, final double tMax) {
// TODO: Implement.
}
/** /**
* Estimate the nearest point for the case of at least one of the * Estimate the nearest point for the case of at least one of the
* coordinates not being possible to match at all. * coordinates not being possible to match at all. Asserts closestX|Y|Z to
* be set to the start coordinates.
* *
* @param tMinX * @param tMinX
* @param tMinY * @param tMinY
@ -118,9 +101,31 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
* @param tMaxY * @param tMaxY
* @param tMaxZ * @param tMaxZ
*/ */
private void findNearestPoint(final double tMinX, final double tMinY, final double tMinZ, private void findNearestPoint(final double... timeValues) {
final double tMaxX, final double tMaxY, final double tMaxZ) { // TODO: Squared vs. Manhattan vs. maxAxis.
// TODO: Implement. // Update squared distance to 'actual'.
closestDistanceSquared = CollisionUtil.getSquaredDistAABB(this.startX, this.startY, this.startZ,
minX, minY, minZ, maxX, maxY, maxZ);
// Find the closest point using set time values.
for (int i = 0; i < timeValues.length; i++) {
final double time = timeValues[i];
if (time == Double.NaN || time == Double.POSITIVE_INFINITY) {
// Note that Double.POSITIVE_INFINITY means that we are colliding forever.
continue;
}
final double x = startX + dirX * time;
final double y = startY + dirY * time;
final double z = startZ + dirZ * time;
final double distanceSquared = CollisionUtil.getSquaredDistAABB(x, y, z,
minX, minY, minZ, maxX, maxY, maxZ);
if (distanceSquared < closestDistanceSquared) {
closestX = x;
closestY = y;
closestZ = z;
closestDistanceSquared = distanceSquared;
closestTime = time;
}
}
} }
@Override @Override
@ -143,6 +148,11 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
return closestZ; return closestZ;
} }
@Override
public double getClosestDistanceSquared() {
return closestDistanceSquared;
}
@Override @Override
public double getTime() { public double getTime() {
return closestTime; return closestTime;

View File

@ -386,4 +386,92 @@ public class CollisionUtil {
} }
} }
/**
* Get the maximum (closest) distance from the given position towards the
* AABB regarding axes independently.
*
* @param x
* Position of the point.
* @param y
* @param z
* @param minX
* Minimum coordinates of the AABB.
* @param minY
* @param minZ
* @param maxX
* Maximum coordinates of the AABB.
* @param maxY
* @param maxZ
* @return
*/
public static double getMaxAxisDistAABB(final double x, final double y, final double z,
final double minX, final double minY, final double minZ,
final double maxX, final double maxY, final double maxZ) {
return Math.max(axisDistance(x, minX, maxX), Math.max(axisDistance(y, minY, maxY), axisDistance(z, minZ, maxZ)));
}
/**
* Get the maximum (closest) 'Manhattan' distance from the given position
* towards the AABB regarding axes independently.
*
* @param x
* Position of the point.
* @param y
* @param z
* @param minX
* Minimum coordinates of the AABB.
* @param minY
* @param minZ
* @param maxX
* Maximum coordinates of the AABB.
* @param maxY
* @param maxZ
* @return
*/
public static double getManhattanDistAABB(final double x, final double y, final double z,
final double minX, final double minY, final double minZ,
final double maxX, final double maxY, final double maxZ) {
return axisDistance(x, minX, maxX)+ axisDistance(y, minY, maxY) + axisDistance(z, minZ, maxZ);
}
/**
* Get the squared (closest) distance from the given position towards the
* AABB regarding axes independently.
*
* @param x
* Position of the point.
* @param y
* @param z
* @param minX
* Minimum coordinates of the AABB.
* @param minY
* @param minZ
* @param maxX
* Maximum coordinates of the AABB.
* @param maxY
* @param maxZ
* @return
*/
public static double getSquaredDistAABB(final double x, final double y, final double z,
final double minX, final double minY, final double minZ,
final double maxX, final double maxY, final double maxZ) {
final double dX = axisDistance(x, minX, maxX);
final double dY = axisDistance(y, minY, maxY);
final double dZ = axisDistance(z, minZ, maxZ);
return dX * dX + dY * dY + dZ * dZ;
}
/**
* Get the distance towards a min-max interval (inside and edge count as 0.0
* distance).
*
* @param pos
* @param minPos
* @param maxPos
* @return Positive distance always.
*/
public static double axisDistance(final double pos, final double minPos, final double maxPos) {
return pos < minPos ? Math.abs(pos - minPos) : (pos > maxPos ? Math.abs(pos - maxPos) : 0.0);
}
} }

View File

@ -6,7 +6,9 @@ import fr.neatmonster.nocheatplus.components.location.IGetPosition;
* Collide a ray with an axis aligned bounding box (AABB). Allow fetching the * Collide a ray with an axis aligned bounding box (AABB). Allow fetching the
* point of time, when the ray is closest to the AABB. The methods getX|Y|Z from * point of time, when the ray is closest to the AABB. The methods getX|Y|Z from
* IGetPosition will fetch the coordinates of collision or the nearest point (if * IGetPosition will fetch the coordinates of collision or the nearest point (if
* set so). By default colliding with the edges of the box would count. * set so). That nearest point may be an estimation, not necessarily consistent
* for all cases/directions. By default colliding with the edges of the box
* would count.
* *
* @author asofold * @author asofold
* *
@ -90,6 +92,14 @@ public interface ICollideRayVsAABB extends IGetPosition {
*/ */
public boolean collides(); public boolean collides();
/**
* Get some kind of squared distance for the nearest point, in case of not
* colliding and findNearestPointIfNotCollid being set.
*
* @return 0.0 if not applicable.
*/
public double getClosestDistanceSquared();
/** /**
* Earliest time of collision if collides() returns true, or of the nearest * Earliest time of collision if collides() returns true, or of the nearest
* point, counted in times of applying the direction. * point, counted in times of applying the direction.