Simple and incomplete implementation for ICollideRayVsAABB.

This commit is contained in:
asofold 2016-06-24 19:04:20 +02:00
parent de2db16d08
commit 3bdb5414ae
4 changed files with 241 additions and 3 deletions

View File

@ -229,6 +229,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
}
// 1.9: sweep attack.
// TODO: Account for charge/meter thing?
final int locHashCode = LocUtil.hashCode(loc);
if (originalDamage == 1.0) {
// Might be a sweep attack.

View File

@ -0,0 +1,151 @@
package fr.neatmonster.nocheatplus.utilities.collision;
public class CollideRayVsAABB implements ICollideRayVsAABB {
private boolean findNearestPointIfNotCollide = false;
/** Start point and direction. */
private double startX, startY, startZ, dirX, dirY, dirZ;
/** Target box (AABB). */
private double minX, minY, minZ, maxX, maxY, maxZ;
/** Collision or closest point. */
private double closestX, closestY, closestZ, closestTime;
/**
* Indicate a collision occurred. Reset with calling loop only.
*/
private boolean collides;
@Override
public ICollideRayVsAABB setRay(double startX, double startY, double startZ,
double dirX, double dirY, double dirZ) {
// Set from parameters.
this.startX = startX;
this.startY = startY;
this.startZ = startZ;
this.dirX = dirX;
this.dirY = dirY;
this.dirZ = dirZ;
return this;
}
@Override
public ICollideRayVsAABB setAABB(double targetX, double targetY, double targetZ,
double boxMarginHorizontal, double boxMarginVertical) {
// Set from parameters.
this.minX = targetX - boxMarginHorizontal;
this.minY = targetY;
this.minZ = targetZ - boxMarginHorizontal;
this.maxX = targetX + boxMarginHorizontal;
this.maxY = targetY + boxMarginVertical;
this.maxZ = targetZ + boxMarginHorizontal;
return this;
}
@Override
public ICollideRayVsAABB setFindNearestPointIfNotCollide(boolean findNearestPointIfNotCollide) {
this.findNearestPointIfNotCollide = findNearestPointIfNotCollide;
return this;
}
@Override
public boolean getFindNearestPointIfNotCollide() {
return findNearestPointIfNotCollide;
}
@Override
public ICollideRayVsAABB loop() {
// Reset results.
collides = false;
closestX = startX;
closestY = startY;
closestZ = startZ;
closestTime = 0.0;
// Determine basic orientation and timing.
final double tMinX = CollisionUtil.getMinTimeIncludeEdges(startX, dirX, minX, maxX);
final double tMinY = CollisionUtil.getMinTimeIncludeEdges(startY, dirY, minY, maxY);
final double tMinZ = CollisionUtil.getMinTimeIncludeEdges(startZ, dirZ, minZ, maxZ);
final double tMaxX = CollisionUtil.getMaxTimeIncludeEdges(startX, dirX, minX, maxX, tMinX);
final double tMaxY = CollisionUtil.getMaxTimeIncludeEdges(startY, dirY, minY, maxY, tMinY);
final double tMaxZ = CollisionUtil.getMaxTimeIncludeEdges(startZ, dirZ, minZ, maxZ, tMinZ);
if (tMaxX != Double.NaN && tMaxY != Double.NaN && tMaxZ != Double.NaN) {
// (Excludes any tMin value to be Double.MAX_VALUE.)
// Determine if there is overlapping intervals.
final double tMin = Math.max(tMinX, Math.max(tMinY, tMinZ));
final double tMax = Math.min(tMaxX, Math.min(tMaxY, tMaxZ));
if (tMin <= tMax) {
collides = true;
closestX = startX + dirX * tMin;
closestY = startY + dirY * tMin;
closestZ = startZ + dirZ * tMin;
}
else if (findNearestPointIfNotCollide) {
findNearestPoint(tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ, tMin, tMax);
}
}
else if (findNearestPointIfNotCollide) {
findNearestPoint(tMinX, tMinY, tMinZ, tMaxX, tMaxY, tMaxZ);
}
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
* coordinates not being possible to match at all.
*
* @param tMinX
* @param tMinY
* @param tMinZ
* @param tMaxX
* @param tMaxY
* @param tMaxZ
*/
private void findNearestPoint(final double tMinX, final double tMinY, final double tMinZ,
final double tMaxX, final double tMaxY, final double tMaxZ) {
// TODO: Implement.
}
@Override
public boolean collides() {
return collides;
}
@Override
public double getX() {
return closestX;
}
@Override
public double getY() {
return closestY;
}
@Override
public double getZ() {
return closestZ;
}
@Override
public double getTime() {
return closestTime;
}
}

View File

@ -302,4 +302,88 @@ public class CollisionUtil {
return db + 1.0 > min && db < max;
}
/**
* Test if a point is inside an AABB, including the edges.
*
* @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 boolean isInsideAABBIncludeEdges(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 !(x < minX || x > maxX || z < minZ || z > maxZ || y < minY || y > maxY);
}
/**
* Get the earliest time a collision with the min-max coordinates can occur,
* in multiples of dir, including edges.
*
* @param pos
* @param dir
* @param minPos
* @param maxPos
* @return The multiple of dir to hit the min-max coordinates, or
* Double.POSITIVE_INFINITY if not possible to hit.
*/
public static double getMinTimeIncludeEdges(final double pos, final double dir,
final double minPos, final double maxPos) {
if (pos >= minPos && pos <= maxPos) {
return 0.0;
}
else if (dir == 0.0) {
return Double.POSITIVE_INFINITY;
}
else if (dir < 0.0) {
return pos < minPos ? Double.POSITIVE_INFINITY : (Math.abs(pos - maxPos) / Math.abs(dir));
}
else {
// dir > 0.0
return pos > maxPos ? Double.POSITIVE_INFINITY : (Math.abs(pos - minPos) / dir);
}
}
/**
* Get the maximum time for which the min-max coordinates still are hit.
*
* @param pos
* @param dir
* @param minPos
* @param maxPos
* @param minTime
* The earliest time of collision with the min-max coordinates,
* as returned by getMinTimeIncludeEdges.
* @return The maximum time for which the min-max coordinates still are hit.
* If no hit is possible, Double.NaN is returned. If minTime is
* Double.POSITIVE_INFINITY, Double.NaN is returned directly.
* Double.POSITIVE_INFINITY may be returned, if coordinates are
* colliding always.
*/
public static double getMaxTimeIncludeEdges(final double pos, final double dir,
final double minPos, final double maxPos, final double minTime) {
if (minTime == Double.POSITIVE_INFINITY) {
return Double.NaN;
}
else if (dir == 0.0) {
return pos < maxPos || pos > maxPos ? Double.NaN : Double.POSITIVE_INFINITY;
}
else if (dir < 0.0) {
return pos < minPos ? Double.NaN : (Math.abs(pos - minPos) / dir);
}
else {
// dir > 0.0
return pos > maxPos ? Double.NaN : (Math.abs(pos - maxPos) / dir);
}
}
}

View File

@ -6,13 +6,15 @@ import fr.neatmonster.nocheatplus.components.location.IGetPosition;
* 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
* IGetPosition will fetch the coordinates of collision or the nearest point (if
* set so).
* set so). By default colliding with the edges of the box would count.
*
* @author asofold
*
*/
public interface ICollideRayVsAABB extends IGetPosition {
// TODO: Control of counting in colliding with the edge?
// TODO: Method to get the maximum per-axis distance in case of not colliding and findNearest... set.
// TODO: Convenience methods to retrieve distances (especially in case of not colliding).
// TODO: Convenience methods for other argument types (vector, IGet..., double[], setAABB(block/ints).
// TODO: Implement fight.visible, use in BlockBreak.direction/visible.
@ -89,8 +91,8 @@ public interface ICollideRayVsAABB extends IGetPosition {
public boolean collides();
/**
* Time of collision if collides() returns true, or of the nearest point,
* counted in times of applying the direction.
* Earliest time of collision if collides() returns true, or of the nearest
* point, counted in times of applying the direction.
*
* @return Time in multiples of the initial direction vector. In case it's
* not possible at all, 0.0 might be returned.