wtorek, 17 marca 2015

Stepping Towards Target Value

When you have some value, name it current, and want to increment it with some constant, name it step, you'd normally do something as simple as this:
current = current + step;
If you wanted to make sure it doesn't step further once it has reached some target value you would do this:
float current = 0.0f;
float target = 1.0f;
float step = 0.1f;

for (;;)
{
    current = current + step;
    if (current > target)
        current = target;
}
Not a big deal. But once I stumbled upon such piece of code:
float current = 0.0f;
float target = 1.0f;
float step = 0.1f;

for (;;)
{
    float delta = fabs(target - current) + 0.0001f;
    float t = Clamp(step / delta);
    current = Lerp(current, target, t);
}
Turns out this code, at first glance looking quite complicated, does the same thing. So, why did the author of that code preferred it this way instead of something more simple as the solution presented in the beginning of this post? I'm not sure. Maybe because this code works correctly when we arbitrarily change target value? For instance, the first solution won't work when target is smaller than current. But we can easily handle this case as well.

Anyway, I was curious to find out that if from mathematical standpoint these two approaches were identical. Here's the proof:
\begin{eqnarray}
a &=& current \cr
b &=& target \cr
s &=& step \cr
t &=& \frac{s}{b-a} \cr
\end{eqnarray}
\begin{eqnarray}
Lerp(a, b, t) = (1-t)a + tb &=& \cr
(a - \frac{s}{b-a}a) + (\frac{s}{b-a}b) &=& \cr
\frac{(b-a)a - sa + sb}{b-a} &=& \cr
\frac{(b-a)a+s(b-a)}{b-a} &=& \cr
a + s
\end{eqnarray}
So, to sum up, the lerp way results in simple incrementation of a with s.

niedziela, 15 marca 2015

Normal Map Generator (from diffuse maps)

In recent days I had a need to generate a normal map from diffuse map. Actually, I had to generate a couple of hundreds normal maps. So I quickly googled for a normal map generator. It's a common "problem" so I was sure a ready-to-use solution had already been there. Turned out I was wrong. Indeed I had stumbled upon a lot of normal map generators but they turned to either be too complex to use, costed money or - what is particularly incomprehensible - none of the programs I had found could run in command-line mode! Not even libs and headers were provided so I could write my own tool. Did they really expect me to click over a couple of hundreds diffuse maps? So eventually I came up with my own program. To my surprise it turned out to be easier than I had initially thought. I bet there are many algorithms for tackling this problem but I really needed anything.

You can get my program's code here. It's written in C# and runs in command-line. The program takes four arguments:
  • input diffuse map file's path
  • output normal map file's path (can be the same as first argument)
  • scale - the bigger this value the bigger the "contrast" of the normal map will be
  • border - width of border of the image filled with (0, 0, 1) normal
I'm not going to describe the algorithm here because the source code is simple enough to easily get a grasp of what's going on.