Forum: Poser - OFFICIAL


Subject: Matmatic question

kobaltkween opened this issue on Nov 29, 2009 · 10 posts


bagginsbill posted Sun, 29 November 2009 at 10:01 AM

Hmm. I really should finish my book. There is a pile of useful stuff like this in the chapters on BUF's, (Basic Unit Functions).

So here's a quick summary. Let's assume you have some control information as input, called "input", just as you said. Let's assume the range of values found in the input is 0 to 1 - what I call "the Unit". I'll show later what to do when your input is not in the unit.

OK. So, you would like to find a function (and therefore a node setup) that blends from one color (or number) to another, given the input from 0 to 1 (i.e. a unit input).

The Poser node that does that is the Blender node. Given two colors (or numbers - works either way), assuming they are c1 and c2, you simply write:

Blender(c1, c2, input)

For example, to get something like the Clouds node (where you have colors as outputs) applied to the fBm unit values:

input = fBm(... your fBm parameters here)
output = Blender(RED, BLUE, input)

Sometimes we do not have an input that is variable. Sometimes we just want to make a color by blending two colors, but it does not need to be dynamic. It can be calculated up front. For this, in matmatic, use the function "Blend" instead of "Blender". Blend is smart. If all the arguments are known at compile time, it will evaluate them and you have just a color. If any are dynamic or variable (i.e. they are nodes) then it will construct a Blender node instead.

For example:

Blend(RED, WHITE, .7) makes a pink color, not a Blender node.

But:

Blend(RED, WHITE, .7 * fBM()) makes a Blender node connected to an fBM node.

Or:

Blend(RED * fBM(), WHITE, .7) also makes a Blender node connected to an fBM node, but the fBm drives the luminance of the first color, not the blending factor.

The Blender node's blending argument (the third one) is automatically clamped, so that if you input is not in "the unit", the values outside "the unit" are forced to be in the unit. I.e., input < 0 becomes 0. Input > 1 becomes 1.

The math behind Blender is easy, and if we did not have a built-in node for it, we could make it like this:

def Blender(c1, c2, f): return (1-f) * c1 + f * c2

But we do not have to, as it is built in to Poser.

If you were to rearrange the math a bit, it is quite obvious how this works.

(1-f) * c1 + f * c2
== c1 - f * c1 + f * c2
== c1 + f * c2 - f * c1
== c1 + f * (c2 - c1)

Aha! Start with color #1 (c1) . Then take some fraction of the difference (c2 - c1) and add that to c1. When f is 0, you just get c1. When f is 1, you add all of the difference from c1 to c2, thus you get c2.

Finally, what if your input data is not in the range 0 to 1. Suppose it is some other bounded range, denoted by lo and hi. Then you can pre-condition the input before using it in the Blend, using a function very similar to the blend function itself, but the inverse of it.

unitInput = (input - lo) / (hi - lo)

For example, suppose you want input value .7 to be RED, 1.5 to be WHITE, and all in-between values interpolated accordingly.

Blend(RED, WHITE, (input - .7) / .8)

would take care of it.

There is a helper function in matmatic that does this. It is called Scale and is a little smarter than the scaling I did here.

To use it in this case I'd say:

Blend(RED, WHITE, Scale(input, .7, 1.5))

That says take the input, and transform the range .7 -> 1.5 into 0 -> 1.


Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)