Improve the raycasting tests and fix a few directional issues

This commit is contained in:
James Seibel
2022-11-19 17:01:29 -06:00
parent 6eb97f654c
commit d3e293db2c
2 changed files with 168 additions and 46 deletions
@@ -30,15 +30,8 @@ import com.seibel.lod.core.util.math.Vec3i;
public class RayCastUtil
{
public static boolean rayIntersectsCube(Vec3d rayStartingPos, Vec3f rayDirection, Vec3i cubeMinPos, int cubeWidth)
{
// the ray must intersect all 3 axis in order to have gone through the cube
return rayIntersectsSquare(rayStartingPos.x, rayStartingPos.z, rayDirection.x, rayDirection.z, cubeMinPos.x, cubeMinPos.z, cubeWidth) &&
rayIntersectsSquare(rayStartingPos.x, rayStartingPos.y, rayDirection.x, rayDirection.y, cubeMinPos.x, cubeMinPos.y, cubeWidth);
}
/**
* this function works for any perpendicular axis, X and Y are just for simplicity and could easily be replaced with X, Y, or Z
* This function should work for any 2 perpendicular axis, X and Y could be replaced with X, Y, or Z
*
* @param rayX the ray's starting X position
* @param rayY the ray's starting Z position
@@ -74,7 +67,7 @@ public class RayCastUtil
// should catch if this was true
return false;
}
else if (isRoughly(Math.abs(rayYDirection), 1, roundingValue))
else if (isRoughly(Math.abs(rayYDirection), 1, roundingValue) || isRoughly(Math.abs(rayXDirection), 0, roundingValue))
{
// slope is straight up or down
@@ -91,13 +84,13 @@ public class RayCastUtil
return rayX >= squareMinX && rayX <= squareMaxX;
}
}
else if (isRoughly(rayYDirection, 0, roundingValue))
else if (isRoughly(Math.abs(rayXDirection), 1, roundingValue) || isRoughly(rayYDirection, 0, roundingValue))
{
// slope is 0 (horizontal line)
// is the ray pointing towards the square?
if ((rayXDirection > 0 && rayX > squareMaxX) || // right
(rayXDirection < 0 && rayX < squareMinX)) // left
(rayXDirection < 0 && rayX < squareMinX)) // left
{
// the ray is pointing away from the square
return false;
@@ -132,7 +125,8 @@ public class RayCastUtil
double yIntersectMax = slope * squareMaxX;
// does the intersection happen before the ray's origin?
if (yIntersectMin <= rayY && (yIntersectMax <= rayY))
if ((rayYDirection > 0 && (yIntersectMin <= rayY && yIntersectMax <= rayY)) || // moving in pos Y direction
(rayYDirection < 0 && (yIntersectMin >= rayY && yIntersectMax >= rayY))) // moving in neg Y direction
{
return false;
}
@@ -153,7 +147,8 @@ public class RayCastUtil
double xIntersectMax = squareMaxY / slope;
// does the intersection happen before the ray's origin?
if (xIntersectMin <= rayX && (xIntersectMax <= rayX))
if ((rayXDirection > 0 && (xIntersectMin <= rayX && xIntersectMax <= rayX)) || // moving in pos X direction
(rayXDirection < 0 && (xIntersectMin >= rayX && xIntersectMax >= rayX))) // moving in neg X direction
{
return false;
}
+160 -33
View File
@@ -21,6 +21,9 @@ package tests;
import com.seibel.lod.core.api.external.methods.data.DhApiTerrainDataRepo;
import com.seibel.lod.core.util.RayCastUtil;
import com.seibel.lod.core.util.math.Vec3d;
import com.seibel.lod.core.util.math.Vec3f;
import com.seibel.lod.core.util.math.Vec3i;
import org.junit.Assert;
import org.junit.Test;
@@ -32,13 +35,8 @@ public class RaycastingTest
{
@Test
public void DemoTest()
public void HorizontalSquareTests()
{
Assert.assertTrue("Example test 1", true);
double rayX, rayY;
double xDir, yDir;
// 1x1 square at (1,1) - (2,2)
double squareMinX = 1;
double squareMinY = 1;
@@ -46,16 +44,12 @@ public class RaycastingTest
//============//
// horizontal //
//============//
// ray points right - direction <1,0>
xDir = 1;
yDir = 0;
double xDir = 1;
double yDir = 0;
// ray origin left of square
rayX = 0;
double rayX = 0;
testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
@@ -73,16 +67,46 @@ public class RaycastingTest
testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray points left - direction <-1,0>
xDir = -1;
yDir = 0;
// ray origin left of square
rayX = 0;
testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 3, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray origin right of square
rayX = 2.5;
testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth);
}
@Test
public void VerticalSquareTests()
{
// 1x1 square at (1,1) - (2,2)
double squareMinX = 1;
double squareMinY = 1;
int squareWidth = 1;
//==========//
// vertical //
//==========//
xDir = 0;
yDir = 1;
// ray points up - direction <0,1>
rayY = 0;
double xDir = 0;
double yDir = 1;
// ray origin under square //
double rayY = 0;
// ray origin below square
testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
@@ -110,14 +134,53 @@ public class RaycastingTest
//=======//
// point //
//=======//
// ray points down - direction <0,-1>
xDir = 0;
yDir = -1;
// ray origin under square //
rayY = 0;
// ray origin below square
testRay(false, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray origin in square
testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray origin above square
rayY = 2.5;
testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 0.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 2.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 3, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
}
@Test
public void PerpendicularSquareTests()
{
// 1x1 square at (1,1) - (2,2)
double squareMinX = 1;
double squareMinY = 1;
int squareWidth = 1;
// AKA the slope is perpendicular to this plane
// direction <0,0>
xDir = 0;
yDir = 0;
double xDir = 0;
double yDir = 0;
testRay(false, 0, 0, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 0.5, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
@@ -128,18 +191,24 @@ public class RaycastingTest
testRay(false, 2.5, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, 3, 3, xDir, yDir, squareMinX, squareMinY, squareWidth);
}
@Test
public void DiagonalSquareTests()
{
// 1x1 square at (1,1) - (2,2)
double squareMinX = 1;
double squareMinY = 1;
int squareWidth = 1;
//==========//
// diagonal //
//==========//
// ray points up right - direction <4,3> (a slope of 3/4)
xDir = 4;
yDir = 3;
// ray points up right - direction <4,3> (a slope of 3/4) //
double xDir = 4;
double yDir = 3;
// ray origin bottom left of square
rayX = 0;
double rayX = 0;
testRay(false, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
@@ -159,14 +228,73 @@ public class RaycastingTest
// ray origin right of square
rayX = 2.5;
rayY = (yDir/xDir) * rayX; // y = mx + b // b is the constants defined below
double rayY = (yDir/xDir) * rayX; // y = mx + b // where b is the constants defined below
testRay(false, rayX, -0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 0 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, 1 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray points down right - direction <-4,3> (a slope of -3/4) //
// move the cube to (1,-2) - (2,-1)
squareMinY = -2;
//xDir = 4;
yDir = -3;
// ray origin bottom left of square
rayX = 0;
testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray origin in square
testRay(true, 1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, 2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray points down left - direction <-4,-3> (a slope of 3/4) //
// move the cube to (-2,-2) - (-1,-1)
//squareMinY = -2;
squareMinX = -2;
xDir = -4;
//yDir = -3;
// ray origin bottom left of square
rayX = 0;
testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth);
// ray origin in square
testRay(true, -1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, -1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth);
testRay(true, -2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth);
}
private static void testRay(boolean expectedToIntersect, double rayX, double rayY, double xDir, double yDir, double squareMinX, double squareMinY, double squareWidth)
{
boolean intersects = RayCastUtil.rayIntersectsSquare(rayX, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth);
@@ -178,5 +306,4 @@ public class RaycastingTest
return "ray: [" + rayX + ", " + rayY + "] <" + xDir + ", " + yDir + "> square: [" + squareMinX + ", " + squareMinY + "] - [" + (squareMinX+squareWidth) + ", " + (squareMinY+squareWidth) + "]";
}
}