开发者

Value Remapping

Processing has a great function I use all the time:

map(value, low1, high1, low2, high2)

http://processing.org/reference/map_.html

It remaps value (that has an expected range of low1 to high1) into a target range of low2 to high2).

I want t开发者_如何学编程o understand the math behind it so I can use it in other languages. Anyone want to throw me a bone and help me reverse engineer it? I understand that it's a lerp that's been re-scaled and re-offset... feeling brain dead this morning.


From your description, it ought to be doing this, right?

low2 + (value - low1) * (high2 - low2) / (high1 - low1)

Find how far you are into the first range, scale that distance by the ratio of sizes of the ranges, and that's how far you should be into the second range.


Processing is open-source. You can view the map() function here.

static public final float map(float value,
                                float start1, float stop1,
                                float start2, float stop2) {
    float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    String badness = null;
    if (outgoing != outgoing) {
      badness = "NaN (not a number)";

    } else if (outgoing == Float.NEGATIVE_INFINITY ||
               outgoing == Float.POSITIVE_INFINITY) {
      badness = "infinity";
    }
    if (badness != null) {
      final String msg =
        String.format("map(%s, %s, %s, %s, %s) called, which returns %s",
                      nf(value), nf(start1), nf(stop1),
                      nf(start2), nf(stop2), badness);
      PGraphics.showWarning(msg);
    }
    return outgoing;
  }

Specifically, you're looking for this line of code:

float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));


I would like to add that is sometimes useful to find the factor between the low1 and high1 so that you can modulate it with a curve before using the factor as a LERP's t.

So, t = (value-low1)/(high1-low1) to get the relative position of value in the line low1 to high1.

Then you can modulate t with some curve filter for example, gamma, bias, gain, etc As also clamp the t between 0 and 1 if you to restrict values that go over the set lows and highs.

And then use the t for the LERP between low2 and high2 like: finalvalue = low2*(1-t) + high2*t


Anyone wondering if there's a float-less version that keeps as much precision as possible, I made this:

int remap(int value, int input_min, int input_max, int output_min, int output_max)
{
    const long long factor = 1000000000;

    long long output_spread = output_max - output_min;
    long long input_spread = input_max - input_min;

    long long l_value = value;

    long long zero_value = value - input_min;
    zero_value *= factor;
    long long percentage = zero_value / input_spread;

    long long zero_output = percentage * output_spread / factor;

    long long result = output_min + zero_output;

    return (int)result;
}

Seems to work for me, not extensively tested (e.g. max is smaller than min is not tested).

The idea behind is it to enlarge the original value by using a bigger type so that divisions yield bigger numbers - which results in more precision.


In my case I used an expression (var * amount)-shift where var is value amount is amount of blendshapes and shift is value based on the index of the blendshape (shift by 1 and you get 0 if the value is 1 so the next blendshape starts of)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜