Skip to content

Math Expressions

McHorse edited this page Jul 4, 2020 · 10 revisions

Thanks to the math modifier, you can apply math expressions to camera fixtures. The syntax of those math expressions are quite simple. Math expressions consist out of following elements:

  • Numbers – 1, 2, 0.5, -10.32, etc.
  • Operators – addition (+), subtraction (-), etc.
  • Variables — variable numbers provided by the math modifier
  • Groups – a pair of parenthesis which makes the operation "more important," i.e. it will be calculated first
  • Functions – a unit that accepts zero or more inputs (arguments) and returns an output

Example of a math expression:

value + sin((t + pt) / 20) * 0.5
  • 20 and 0.5 are constant numbers
  • +, / and * are operators
  • value, t and pt are variables
  • (t + pt) is a group
  • sin(...) is a function

Operators

Math expression supports following operators:

Representation Precedence value Description
+ 1 Addition operator, i.e. 2 + 3 = 5
- 1 Subtraction operator, i.e. 5 - 3 = 2
* 2 Multiplication operator, i.e. 4 * 3 = 12
/ 2 Division operator, i.e. 12 / 6 = 2
% 2 Modulo operator, which is also known as remainder of division, i.e. 21 % 5 = 1
^ 3 Power operator, i.e. 2^4 = 2 * 2 * 2 * 2, 4^0.5 = sqrt(4) = 2

Since McLib 2.0, there are also logical boolean and number comparison operators:

Representation Precedence value Description
&& 5 Logical AND operator, returns 1 if both operands are non-zero, i.e. 3 && 5 = 1, 0 && 25 = 0, 5 && 0 = 0
|| 5 Logical OR operator, returns 1 if only one operand non-zero, i.e. 3 || 5 = 1, 0 || 25 = 1, 5 && 0 = 1, 0 || 0 = 0
< 5 Less than operator, 1 if left operand is less than or second operand, i.e. 2 <= 5 = 1, 2 <= 2 = 1, 5 <= 2 = 0
<= 5 Less than or equal to operator, 1 if left operand is less than or equal to than second, i.e. 2 < 5 = 1, 5 < 2 = 0
> 5 Greater than operator, 1 if left operand is greater than to second operand, i.e. 2 <= 5 = 1, 2 <= 2 = 1, 5 <= 2 = 0
>= 5 Greater than or equal to operator, 1 if left operand is greater than or equal to than second, i.e. 2 < 5 = 1, 5 < 2 = 0
== 5 Equals to operator, 1 if left operand equals to second, i.e. 1 == 2 = 0, 1 == 1 = 1
!= 5 Not equals to operator, 1 if left operand isn't equal to second, 1 != 2 = 1, 1 != 1 = 0
! 5 Negate operator, 1 if right operand is 0, and 0 if right operand is not 0, it supports only the right operand, i.e. !5 = 0, !0 = 1

Note: Operands are basically the left and right parts from operator, so, Here are a couple of examples:

  • 1 + 5, 1 and 5 are left and right operands, respectively.
  • pt + (t / 5), pt and (t / 5) are left and right operands, respectively. Note: even though (t / 5) is a group that has an operator inside, it's an operand relative to the outer expression pt + (t / 5).
  • 5 * sin(o), 5 and sin(o) are left and right operands, respectively.

Operator precedence

Besides their own operations, operators also affect the order of calculations. Every operator has its own value of precedence. During the operator comparison, if the precedence value of right operator is greater, then right operator is getting calculated before left operator, otherwise left operator gets executed before right.

Here is an example of how it works. For better comprehension, the end result is getting grouped. An example of right operator having greater precedence value:

1 + 2 * 3
  =
(1 + (2 * 3))

An example of left operator having greater precedence value:

1 * 2 + 3
  =
((1 * 2) + 3)

And finally, an example of both operators having same precedence value:

1 + 2 + 3
  = 
((1 + 2) + 3)

Ternary operator

Beside usually operators, there is also a logical ternary operator whose syntax is:

(logical_test ? if_true : if_false)

Where logical_test, if_true and if_false are math expressions. If logical_test returns a non-zero value, then it will return if_true, otherwise, if logical_test is 0, then it will return if_false. For example:

  • 5 < 10 ? 25 : 100 = 25, because 5 is less than 10
  • random() < 0.5 ? 10 : -10 will return 10 if random() is less than 0.5, and -10 if it's more or equal to 0.5
  • !0 ? (2 + 6) : 4 = 8, which is (2 + 6), because !0 = 1 and it's a non-zero value, which yields (2 + 6)

Variables

Variables allow you to use some values passed by the math modifier. Here is the list of supported variables within math modifier.

General variables

  • PI – Pi (π)
  • E – Euler's number

Input

These variables are directly taken from fixture's result.

  • x – X coordinate of camera's position.
  • y – Y coordinate of camera's position.
  • z – Z coordinate of camera's position.
  • yaw – camera's yaw.
  • pitch – camera's pitch.
  • roll – camera's roll.
  • fov – camera's Field-Of-View.
  • value – this variable is takes whatever value is currently getting processed, based on the toggle bar under math expression textfield. For example, if in math modifier, Yaw and Pitch are toggled, value variable will become first yaw, and then pitch (consequently).

Time and progress

These variables below signify of how far the camera playback into the camera profile.

  • t – how many ticks passed since beginning of camera playback.
  • o – how many ticks passed since current camera fixture.
  • d – how long (in ticks) current camera fixture is.
  • pt – partial tick, basically how far rendering into the update tick (from 0.0 to 1.0). This variable is needed for interpolation (and smoothing).
  • p – sum of t and pt variables.

Groups

Groups are quite simple, they're grouping the calculation and giving that expression a higher precendence value over other operators, so if you need to isolate some calculation, you can group your calculations.

Functions

With usage of functions you can process variables or constant values into something else. Math modifier supports following functions:

Name Description
abs(x) Absolute value function, basically always returns a positive x.
clamps(x, min, max) Limits x between min and max.
cos(x) Cosine of x
floor(x) Rounds x to bottom (i.e. removing numbers after floating point). Using floor(x) you can derive round(x) = floort(x + 0.5) and ceil(x) = floor(x + 1).
sin(x) Sine of x
random([range/start], [end], [seed]) Returns a random number. See the section below for more information.

Since McLib 2.0, following functions were added:

Name Description
round(x) round x to nearest integer
ceil(x) round x to upper integer
trunc(x) truncate x, floor x when x is positive, and ceil x when it's negative
max(a, b) return a bigger value between a and b
min(a, b) return a smaller value between a and b
exp(x) e constant to the power of x
ln(x) natural logarithm of x
sqrt(x) square root of x
mod(x, d) get remainder of x divided by d, equivalent to x % d
pow(x, d) x to the power of p, equivalent to x^p
lerp(a, b, x) linearly interpolate between a to b using x as a factor, same as a + (b - a) * x
lerprotate(a, b, x) same as lerp(a, b, x), however, it also normalizes rotation degrees so they wouldn't go multiple 360 circles around

If you have any suggestions for variables or functions, feel free to create an issue describing a list of variables/functions you want to be added to math expressions.

About random()

All arguments in random() function are optional, so there are four scenarios of what it could return, but all of them will be pseudo random numbers:

  • If no arguments were provided, it will return a random number between 0 and 1 every time.
  • If range/start argument passed, it will return a value between 0 and range/start.
  • If range/start and end arguments were passed, a random value between range/start and end will be returned.
  • Finally, if all arguments were provided, then a seeded (meaning for every seed there will be the same random number) random value will be returned between range/start and end. seed accepts only integer (long) values, so make sure to multiply seed by 10 of any power (10^2, 10^3, etc.) to get more rapid random results if you use variables such as p.

Examples

Random camera shake

value + random(-2.5, 2.5)

Apply this math expression on Yaw and Pitch (toggle those), and you'll get a random shake, instead of smooth shake provided by shake modifier. -2.5 and 2.5 here are how much it would shake by yaw and pitch.

If you want it to be consistent every time after playback, i.e. still random, but reproduce the same randomness, change to following math expression:

value + random(-2.5, 2.5, (value + p) * 100000)

Where (value + p) * 100000 is the [seed] of random function which allows to make it more consistent.

Limiting camera angles

Let's say you have a path, and you don't want the camera turn past 90 degrees on Yaw. You can use following math expression to limit the yaw in that direction:

min(value, 90)

This expression will use minimum function to yield a lower value, if value is more than 90, the function will return 90. Make sure to enable "Display position" property to figure out actual values of your yaw, as they will get normalized.

Circular movement without circular fixture

Let's say you want to add circular movement to your path fixture, however, you can't use both circular and path fixtures together. You need to add two math modifiers with following expressions:

/* This first expression is for X */
value + cos(p / 20) * 10

/* This first expression is for Z */
value + sin(p / 20) * 10

Where / 20 determines the speed of circular movement, the higher the value, the slower it revolves around the circle and 10 is the radius of the circle.