-
-
Notifications
You must be signed in to change notification settings - Fork 17
Math Expressions
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
and0.5
are constant numbers -
+
,/
and*
are operators -
value
,t
andpt
are variables -
(t + pt)
is a group -
sin(...)
is a function
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
and5
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 expressionpt + (t / 5)
. -
5 * sin(o)
,5
andsin(o)
are left and right operands, respectively.
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)
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 return10
ifrandom()
is less than0.5
, and-10
if it's more or equal to0.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 allow you to use some values passed by the math modifier. Here is the list of supported variables within math modifier.
-
PI
– Pi (π) -
E
– Euler's number
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
andPitch
are toggled,value
variable will become firstyaw
, and thenpitch
(consequently).
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 (from0.0
to1.0
). This variable is needed for interpolation (and smoothing). -
p
– sum oft
andpt
variables.
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.
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.
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
and1
every time. - If
range/start
argument passed, it will return a value between0
andrange/start
. - If
range/start
andend
arguments were passed, a random value betweenrange/start
andend
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
andend
.seed
accepts only integer (long
) values, so make sure to multiplyseed
by 10 of any power (10^2
,10^3
, etc.) to get more rapid random results if you use variables such asp
.
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.
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.
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.