- Changeable player skins. - Ammo LEDs are now 1:1 with UT by using canvas textures. - Integrate some add-ons, including reskins. - Various fixes (some backported from Demolitionist). - Migrated from libeye to Gutamatics.
173 lines
5.5 KiB
Text
173 lines
5.5 KiB
Text
class dt_GM_GlobalMaths {
|
|
/// Returns the sign of s.
|
|
static int sign(double s) {
|
|
if (s > 0) return 1;
|
|
if (s < 0) return -1;
|
|
return 0;
|
|
}
|
|
|
|
/// Copies the sign from signSource to source.
|
|
static int copySignInt(int source, int signSource) {
|
|
return abs(source) * sign(signSource);
|
|
}
|
|
|
|
/// Copies the sign from signSource to source.
|
|
static double copySignDouble(double source, double signSource) {
|
|
return abs(source) * sign(signSource);
|
|
}
|
|
|
|
/// Remaps a value in a range to another range.
|
|
static double remapRange(double value, double range1L, double range1H, double range2L, double range2H) {
|
|
return range2L + (value - range1L) * (range2H - range1H) / (range1H - range1L);
|
|
}
|
|
|
|
/// Remaps a value in a range to another range.
|
|
static int remapRangeInt(int value, int range1L, int range1H, int range2L, int range2H) {
|
|
return int(range2L + (value - range1L) * (range2H - range1H) / double(range1H - range1L));
|
|
}
|
|
|
|
/// Returns if two values are close enough to be considered equal.
|
|
static bool closeEnough(double a, double b, double epsilon = double.epsilon) {
|
|
if (a == b) return true;
|
|
return abs(a - b) <= epsilon;
|
|
}
|
|
|
|
// Creates a smoothed transition between edge0 and edge1.
|
|
static double smoothStep(double x, double edge0 = 0, double edge1 = 1) {
|
|
x = clamp((x - edge0) / (edge1 - edge0), 0, 1);
|
|
return x * x * (3 - 2 * x);
|
|
}
|
|
|
|
// Creates a smoother transition between edge0 and edge1.
|
|
static double smootherStep(double x, double edge0 = 0, double edge1 = 1) {
|
|
x = clamp((x - edge0) / (edge1 - edge0), 0, 1);
|
|
return x * x * x * (x * (x * 6 - 15) + 10);
|
|
}
|
|
|
|
/// Converts from horizontal FOV to vertical FOV, according to how GZDoom handles it.
|
|
static double fovHToY(double fovH) {
|
|
// this is how gzdoom does it internally, so i'm using it here
|
|
double aspect = Screen.getAspectRatio();
|
|
double fovratio = (aspect >= 1.3) ? 1.333333 : aspect;
|
|
return 2 * atan(tan(clamp(fovH, 5, 170) / 2.0) / fovratio);
|
|
}
|
|
|
|
/// Linearly interpolates between two doubles, clamping the parameters.
|
|
static double lerpDouble(double from, double to, double time) {
|
|
time = clamp(time, 0, 1);
|
|
return lerpUnclampedDouble(from, to, time);
|
|
}
|
|
|
|
/// Linearly interpolates between two doubles.
|
|
static double lerpUnclampedDouble(double from, double to, double time) {
|
|
double ret;
|
|
double reverseTime = 1 - time;
|
|
ret = reverseTime * from + time * to;
|
|
return ret;
|
|
}
|
|
|
|
// Converts from Normalised Device Coordinates to Viewport coordinates.
|
|
// This is `ui` scope to safely access `screenblocks`.
|
|
static ui Vector2 ndcToViewport(Vector3 ndcCoords, bool useScreenblocks = true) {
|
|
if (useScreenblocks) {
|
|
int viewwindowx, viewwindowy, viewwidth, viewheight;
|
|
[viewwindowx, viewwindowy, viewwidth, viewheight] = Screen.getViewWindow();
|
|
int screenHeight = Screen.getHeight();
|
|
int height = screenHeight;
|
|
if (screenblocks < 10) {
|
|
height = (screenblocks * screenHeight / 10) & ~7;
|
|
}
|
|
int bottom = screenHeight - (height + viewwindowy - ((height - viewheight) / 2));
|
|
return (viewwindowx, screenHeight - bottom - height) + (((ndcCoords.x + 1) * viewwidth) / 2, ((-ndcCoords.y + 1) * height) / 2);
|
|
}
|
|
else {
|
|
return (((ndcCoords.x + 1) * Screen.getWidth()) / 2, ((-ndcCoords.y + 1) * Screen.getHeight()) / 2);
|
|
}
|
|
}
|
|
|
|
enum OutCode {
|
|
OUT_Inside = 0,
|
|
OUT_Left = 1 << 0,
|
|
OUT_Right = 1 << 1,
|
|
OUT_Bottom = 1 << 2,
|
|
OUT_Top = 1 << 3
|
|
}
|
|
|
|
/// Computes an outcode for a point in a rectangle.
|
|
static OutCode computeOutcode(Vector2 point, Vector2 min, Vector2 max) {
|
|
OutCode code = OUT_Inside;
|
|
|
|
if (point.x < min.x) {
|
|
code |= OUT_Left;
|
|
}
|
|
else if (point.x > max.x) {
|
|
code |= OUT_Right;
|
|
}
|
|
if (point.y < min.y) {
|
|
code |= OUT_Top;
|
|
}
|
|
else if (point.y > max.y) {
|
|
code |= OUT_Bottom;
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
/// Clips a line to a rectangle.
|
|
static bool, Vector2, Vector2 cohenSutherlandClip(Vector2 point0, Vector2 point1, Vector2 min, Vector2 max) {
|
|
OutCode outcode0 = computeOutCode(point0, min, max);
|
|
OutCode outcode1 = computeOutCode(point1, min, max);
|
|
|
|
while (true) {
|
|
// trivial accept - points are both on screen
|
|
if ((outcode0 | outcode1) == 0) {
|
|
return true, point0, point1;
|
|
}
|
|
// trivial reject - points are in the same region offscreen
|
|
else if ((outcode0 & outcode1) != 0) {
|
|
return false, point0, point1;
|
|
}
|
|
else {
|
|
Vector2 new;
|
|
OutCode outcodeOut = (outcode0 != 0) ? outcode0 : outcode1;
|
|
|
|
if ((outcodeOut & OUT_Bottom) != 0) {
|
|
new.x = point0.x + (point1.x - point0.x) * (max.y - point0.y) / (point1.y - point0.y);
|
|
new.y = max.y;
|
|
}
|
|
else if ((outcodeOut & OUT_Top) != 0) {
|
|
new.x = point0.x + (point1.x - point0.x) * (min.y - point0.y) / (point1.y - point0.y);
|
|
new.y = min.y;
|
|
}
|
|
else if ((outcodeOut & OUT_Right) != 0) {
|
|
new.y = point0.y + (point1.y - point0.y) * (max.x - point0.x) / (point1.x - point0.x);
|
|
new.x = max.x;
|
|
}
|
|
else if ((outcodeOut & OUT_Left) != 0) {
|
|
new.y = point0.y + (point1.y - point0.y) * (min.x - point0.x) / (point1.x - point0.x);
|
|
new.x = min.x;
|
|
}
|
|
|
|
if (outcodeOut == outCode0) {
|
|
point0.x = new.x;
|
|
point0.y = new.y;
|
|
outCode0 = computeOutCode(point0, min, max);
|
|
}
|
|
else {
|
|
point1.x = new.x;
|
|
point1.y = new.y;
|
|
outCode1 = computeOutCode(point1, min, max);
|
|
}
|
|
}
|
|
}
|
|
return false, (0, 0), (0, 0);
|
|
}
|
|
|
|
// Normalizes an angle to (-180, 180]. Like Actor.normalize180, but callable in data scope.
|
|
static double normalize180(double ang) {
|
|
ang = ang % 360;
|
|
ang = (ang + 360) % 360;
|
|
if (ang > 180) ang -= 360;
|
|
return ang;
|
|
}
|
|
}
|