Implement RegionShape.POLYGON and RegionShape.CYLINDER (#2348)

Also took the opportunity to sort them in order and use multiplication instead of pow.
This commit is contained in:
Nazrin 2023-09-08 20:06:14 -07:00 committed by GitHub
parent cdcdf924bd
commit a9402f487f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -30,16 +30,48 @@ public class SceneRegion {
public boolean contains(Position position) {
switch (shape) {
case ScriptRegionShape.CUBIC:
case ScriptRegionShape.SPHERE -> {
val x = pos.getX() - position.getX();
val y = pos.getY() - position.getY();
val z = pos.getZ() - position.getZ();
// x^2 + y^2 + z^2 = radius^2
return x * x + y * y + z * z <= radius * radius;
}
case ScriptRegionShape.CUBIC -> {
return (Math.abs(pos.getX() - position.getX()) <= size.getX() / 2f)
&& (Math.abs(pos.getY() - position.getY()) <= size.getY() / 2f)
&& (Math.abs(pos.getZ() - position.getZ()) <= size.getZ() / 2f);
case ScriptRegionShape.SPHERE:
var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 2);
var z = Math.pow(pos.getZ() - position.getZ(), 2);
// ^ means XOR in java!
return x + y + z <= (radius * radius);
}
case ScriptRegionShape.POLYGON -> {
// algorithm is "ray casting": https://www.youtube.com/watch?v=RSXM9bgqxJM
if (Math.abs(pos.getY() - position.getY()) > height / 2f) return false;
var count = 0;
for (var i = 0; i < point_array.size(); ++i) {
val j = (i + 1) % point_array.size();
val yp = position.getZ();
val y1 = point_array.get(i).getY();
val y2 = point_array.get(j).getY();
val xp = position.getX();
val x1 = point_array.get(i).getX();
val x2 = point_array.get(j).getX();
if ((yp < y1) != (yp < y2)
&& xp < x1 + ((yp - y1) / (y2 - y1)) * (x2 - x1)) {
++count;
}
}
return count % 2 == 1;
}
case ScriptRegionShape.CYLINDER -> {
if (Math.abs(pos.getY() - position.getY()) > height / 2f) return false;
val x = pos.getX() - position.getX();
val z = pos.getZ() - position.getZ();
// x^2 + z^2 = radius^2
return x * x + z * z <= radius * radius;
}
}
return false;
}