mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 03:05:34 +00:00
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:
parent
cdcdf924bd
commit
a9402f487f
@ -30,16 +30,48 @@ public class SceneRegion {
|
||||
|
||||
public boolean contains(Position position) {
|
||||
switch (shape) {
|
||||
case ScriptRegionShape.CUBIC:
|
||||
return (Math.abs(pos.getX() - position.getX()) <= size.getX() / 2f)
|
||||
&& (Math.abs(pos.getY() - position.getY()) <= size.getY() / 2f)
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user