SVF is fine.
TL;DR in exponential mapping, the boundaries of the range must not cross or touch 0.
- 1, 5 – OK, both nonzero and positive
- -5, -1 – OK, both nonzero and negative
- -1, 5 – not OK, mixed signs
- 0, 5 – not OK, touches 0
- -5, 0 – not OK, touches 0
Why?
In my class, I first introduce the idea of mapping a normal range (0 … 1) onto a desired output range. Starting with a normal range simplifies the math.
Linear mapping is then based on the difference between the boundaries: if x
is the normalized input, y = (b - a) * x + a
.
Exponential mapping is based on the ratio between the boundaries: b / a
instead of b - a
. One way that I think of this is “promoting” operators: subtraction gets pushed up to division (and addition, up to multiplication); and the * x
gets pushed up to power-of.
(
f = { |x, a = 1, b = 2|
(b / a) ** x * a;
};
)
f.(0.5, 1, 0);
-> 0
f.(0.0, 1, 0);
-> 1.0
f.(0.5, 0, 1);
-> -nan
f.(0.5, -1, 1);
-> -nan
If b is 0, then b/a = 0, and every nonzero x will produce 0! Which is correct according to the formula, but not useful, so, don’t do it. (x == 0 produces 1.0 – which is a dodge because mathematically, 0.0 ** 0.0 is undefined – there are plenty of YouTube videos explaining this, I won’t repeat it here.)
If a is 0, then b/a = inf, and the result is “not a number” (this is an actual special-case floating-point value, for invalid calculations).
If b/a is negative, then raising that to a fractional power is very likely to require imaginary numbers (-4 ** 0.5 is invalid, but Complex(-4, 0) ** 0.5 == Complex( 1.2246467991474e-16, 2.0 ) which is 2i once you ignore the floating-point rounding error)… but floating-point is in the real-number domain, so, it can’t be done (NaN again).
The 0 in your MouseY is OK for linear mapping, but mathematically impossible for exponential mapping. You will have to change the lower limit to a positive value when switchwarp
is 2, e.g., MouseY.kr((switchwarp >= 2) * 0.01, 0.96, switchwarp)
.
hjh