Change of base formula for `math.log()`

expressions:

```
local function log_base(base, expression)
return math.log(expression) / math.log(base)
end
```

Change of base formula for `math.log()`

expressions:

```
local function log_base(base, expression)
return math.log(expression) / math.log(base)
end
```

Check if `value`

is between `min`

and `max`

:

```
local function is_within_range(value, min, max)
return min <= value and value <= max
end
```

Calculate Manhattan distance between two points:

```
local function manhattan_distance(from, to)
return vmath.vector3(to.x - from.x, to.y - from.y, to.z - from.z)
end
```

Get the sign of a number (1 for positive numbers, -1 for negative numbers, and 0 for zero):

```
local function sign(n)
return n > 0 and 1 or (n < 0 and -1 or 0)
end
```

Converts a hex string to a vector4

```
function hex_to_color(hex)
local r, g, b = hex:match("#(%x%x)(%x%x)(%x%x)")
r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16)
return vmath.vector4(r / 255, g / 255, b / 255, 1)
end
```

1 Like

Great idea!

This is a function which I find that I often need myself. I wonder if it should be part of vmath?

7 Likes

Check if `point`

is within `rectangle`

:

```
local function is_within_rectangle(point_x, point_y, rect_x, rect_y, rect_width, rect_height)
return rect_x <= point_x and point_x <= rect_x + rect_width and rect_y <= point_y and point_y <= rect_y + rect_height
end
```

I think that would be a good addition. Maybe better for the `math`

module, but if I understand correctly, `math`

is built into the Lua language.

Here’s a bunch of stuff I collected over the years:

Also, a good animation tool I’ve found useful are low-pass filters for creating snapping effects or smoothing out movements:

https://github.com/critique-gaming/crit/blob/master/crit/filters.lua

4 Likes

I wrote this function when I was trying to pprint some enormous tables full of subtables.

```
--individually prints each line of a nested table
local function recursive_pprint(t, table_name)
if not t then
return
end
table_name = table_name or ""
local type_table = "table"
for key, value in pairs(t) do
if type(value) == type_table then
recursive_pprint(value, key)
else
print(table_name .. ": " .. key .. ": ", value)
end
end
```

4 Likes

Awesome. I actually have something similar too. See `table_util.dump()`

above. The cool part is that it outputs valid Lua most of the time

3 Likes

Accurate framerate-independent lerp with delta-time:

```
-- `rate` is the lerp coefficient per second. So rate=0.5 halves the difference every second.
local function lerpdt(from, to, rate, dt)
local diff = from - to -- Target value is just an offset. Remove it and add it back.
return diff * (1 - rate)^dt + to -- Flip rate so it's the expected direction (0 = no change).
end
```

Thanks to this site for the correct explanation.

Normally, the `rate`

is the lerp coefficient *per second*. To adjust the time frame, divide `dt`

by the desired time.

For example, if you want to halve a value every 1/60th of a second, do:

`lerpdt(from, to, 0.5, dt/(1/60))`

Has been unit tested. A basic test:

```
from, to, rate = 10, 0, 0.25
-- Lerp over 1 second all at once:
local result = lerpdt(from, to, rate, 1)
-- Lerp iteratively with times adding up to 1:
from = lerpdt(from, to, rate, 0.75)
from = lerpdt(from, to, rate, 0.01)
from = lerpdt(from, to, rate, 0.21)
from = lerpdt(from, to, rate, 0.01)
from = lerpdt(from, to, rate, 0.01)
from = lerpdt(from, to, rate, 0.01)
-- `from` and `result` should be equal (with some floating point error).
```

4 Likes

Thanks everyone. I will change the list in the first post to include categories to improve organization.

I’m having some trouble seeing how this is different than `vmath.lerp()`

example from the docs: API reference (vmath)

It looks to me like the new part is the `rate`

parameter?

The function I posted is framerate-independent. It can be used *continuously* in update() (i.e. without having a start and end time to the interpolation).

Let’s say you have a value that you want to halve every frame. Maybe you’re remaking Nuclear Throne and you want to damp the velocity of a shotgun bullet. If you do:

```
function update(self, dt)
self.velocity = vmath.lerp(0.5, self.velocity, 0)
end
```

That is wrong. It will vary quite a bit depending on your framerate.

This is also wrong:

```
self.velocity = vmath.lerp(0.5*dt, self.velocity, 0)
```

Basically, you need this any time you want to *continuously* move one value towards another. Camera smoothing is another good example.

6 Likes

One of my favorite Lua function libs:

7 Likes

Hmm. That looks interesting. It’s definitely not a “LERP” since that’s a linear interpolation and the result here is not linear. More rather it’s sort-of like a low-pass filter, as in a function that always tends towards the target (if you take its limit), but “lags behind” a bit hence cutting off any abrupt movements (higher frequencies). I’m happy to see I’m not the only one using low pass filters for animation, yay!

I use this version lifted off the Wikipedia article on low pass filters:

```
-- @tparam number cutoff_frequency The cut-off frequency (in Hz) of the filter.
-- @treturn LowPassFilter The new filter function.
function M.low_pass(cutoff_frequency)
local RC = 1.0 / (cutoff_frequency * 2.0 * math.pi);
return function (previous_output, input, dt)
local alpha = dt / (dt + RC);
return previous_output + alpha * (input - previous_output);
end
end
```

8 Likes

Yes, the clamp function is really useful. Is it part of vmath now?

1 Like

No, we haven’t made any additions to vmath.

Just a module with list of “incoming” message ids and “shortcuts” for sending standard Defold messages. You can download it from Github defold-lua-annotations releases (look for `defoldy-X.X.X.zip`

in release assets). In example defoldy-1.5.0.zip for Defold v1.5.0.

7 Likes