Page 1 of 1

### Distance between two points Posted: Mon Jan 15, 2018 8:33 pm
Hello

I was trying to autofocus a camera using the dist3D expression described on manual, page 755

dist3d(x1,y1,z1,x2,y2,z2)

So I tried with this, to get the distance between the camera and its target (this time I want focus to target, but it could be another object):

Code: Select all
`dist3d(Transform3DOp.Translate.X,Transform3DOp.Translate.Y,Transform3DOp.Translate.Z,Transform3DOp.Target.X,Transform3DOp.Target.Y,Transform3DOp.Target.Z)`

It does not work, so I simplified to

dist3d(0,0,0,10,10,10)

this should return a value of 17,3 (the distance between 0,0,0 and 10,10,10) but does not work neither, so I must be missing something very basic.

Any cue?

### Re: Distance between two points Posted: Mon Jan 15, 2018 9:04 pm
it works if I write the full classic equation

Code: Select all
`sqrt(((Transform3DOp.Target.X-Transform3DOp.Translate.X)^2)+((Transform3DOp.Target.Y-Transform3DOp.Translate.Y)^2)+((Transform3DOp.Target.Z-Transform3DOp.Translate.Z)^2))`

so I go back to my project, but keep wondering what was wrong with dist3d

### Re: Distance between two points Posted: Mon Jan 15, 2018 9:46 pm
It looks like dist() and dist3d() only work in the Expression Modifier. There are a few that are like that. It's possible that if you can figure out what library the functions are drawn from you would be able to use them in Simple Expressions.

For instance, sin() only works in the Expression modifier or CustomTool. Elsewhere you can access it with math.sin().

### Re: Distance between two points Posted: Mon Jan 15, 2018 10:11 pm
but I'm right now animating the x position os a emitter with a simple

sin(time)

as expression in the emitter x position, and works fine.

Edit: Youre right, dist3d works fine in the modifier.

Now trying to figure a function to make a linear oscilation movement. sin(time) gives nice eased curve, but this time I need constant speed. Controlable amplitude keeping constant speed. Hmmm.

Edit:
time%(amplitude+1) loops values between 0 and amplitude. But... how can I convert that loop in a ping-pong? I wish I knew more maths now edit2

I think I have it:

-1^int(time/a) oscilates the sign (positive/negative) every a frames.

### Re: Distance between two points Posted: Mon Jan 15, 2018 11:14 pm
I think I gave you some very old info. Yeah, the trig functions work just fine in Simple Expressions. Not sure what I was thinking about. Anyway, if you need some wave expressions, I have a macro:

Code: Select all
`{   Tools = ordered() {      MT_Glitch_Waves = MacroOperator {         CtrlWZoom = false,         Inputs = ordered() {            Comments = Input { Value = "A collection of wave-generating expressions.\r\n\r\nMuse Tools, Glitch Tools Collection\r\nby Bryan Ray\r\nwww.musevfx.com", },            Sin = InstanceInput {               SourceOp = "Waves",               Source = "SineWave",               Expression = "(sin(2*pi*time/Period) + 1) / 2 * (Maximum-Minimum) + Minimum",               Default = 0.9829629131445,            },            Triangle = InstanceInput {               SourceOp = "Waves",               Source = "TriangleWave",               Expression = "(asin(sin(2*pi*time/Period))/pi+0.5) * (Maximum-Minimum) + Minimum",               Default = 0.9166666666667,            },            Square = InstanceInput {               SourceOp = "Waves",               Source = "SquareWave",               Expression = "floor(SineWave + 0.5)",               Default = 1,            },            Sawtooth = InstanceInput {               SourceOp = "Waves",               Source = "SawtoothWave",               Expression = "(time%Period)/Period *  (Maximum-Minimum) + Minimum",               Default = 0.2916666666667,            },            Parabolic = InstanceInput {               SourceOp = "Waves",               Source = "ParabolicSawtoothWave",               Expression = "sin(( (pi*time) / (2*Period) ) % (pi/2)) *  (Maximum-Minimum) + Minimum",               Default = 0.442288690219,            },            ReverseParabolic = InstanceInput {               SourceOp = "Waves",               Source = "ReversedParabolicSawtoothWave",               Expression = "cos(( (pi*time) / (2*Period) ) % (pi/2)) * (Maximum-Minimum) + Minimum",               Default = 0.8968727415327,            },            Exponential = InstanceInput {               SourceOp = "Waves",               Source = "ExponentialSawtoothWave",               Expression = "(exp((2*pi*(time % Period))/Period) - 1)/exp(2*pi)",               Default = 0.0098042406716,            },            Bounce = InstanceInput {               SourceOp = "Waves",               Source = "BounceWave",               Expression = "abs(sin(pi*time/Period)) *  (Maximum-Minimum) + Minimum",               Default = 0.7933533402912,            },            Min = InstanceInput {               SourceOp = "Waves",               Source = "Minimum",               Default = 0,            },            Max = InstanceInput {               SourceOp = "Waves",               Source = "Maximum",               Default = 1,            },            Period = InstanceInput {               SourceOp = "Waves",               Source = "Period",               Default = 24,            }         },         ViewInfo = GroupInfo { Pos = { 330, 16.5 } },         Tools = ordered() {            Waves = BrightnessContrast {               CtrlWZoom = false,               CtrlWShown = false,               NameSet = true,               Inputs = {                  Blend = Input { Value = 0, },                  ProcessRed = Input { Value = 0, },                  ProcessGreen = Input { Value = 0, },                  ProcessBlue = Input { Value = 0, },                  ProcessAlpha = Input { Value = 0, },                  Red = Input { Value = 1, },                  Green = Input { Value = 1, },                  Blue = Input { Value = 1, },                  Gain = Input { Value = 1, },                  Gamma = Input { Value = 1, },                  Saturation = Input { Value = 1, },                  High = Input { Value = 1, },                  SineWave = Input {                     Value = 0.982962913144534,                     Expression = "(sin(2*pi*time/Period) + 1) / 2 * (Maximum-Minimum) + Minimum",                  },                  TriangleWave = Input {                     Value = 0.916666666666667,                     Expression = "(asin(sin(2*pi*time/Period))/pi+0.5) * (Maximum-Minimum) + Minimum",                  },                  SquareWave = Input {                     Value = 1,                     Expression = "floor(SineWave + 0.5)",                  },                  SawtoothWave = Input {                     Value = 0.291666666666667,                     Expression = "(time%Period)/Period *  (Maximum-Minimum) + Minimum",                  },                  ParabolicSawtoothWave = Input {                     Value = 0.442288690219001,                     Expression = "sin(( (pi*time) / (2*Period) ) % (pi/2)) *  (Maximum-Minimum) + Minimum",                  },                  ReversedParabolicSawtoothWave = Input {                     Value = 0.896872741532688,                     Expression = "cos(( (pi*time) / (2*Period) ) % (pi/2)) * (Maximum-Minimum) + Minimum",                  },                  ExponentialSawtoothWave = Input {                     Value = 0.00980424067164143,                     Expression = "(exp((2*pi*(time % Period))/Period) - 1)/exp(2*pi)",                  },                  BounceWave = Input {                     Value = 0.793353340291235,                     Expression = "abs(sin(pi*time/Period)) *  (Maximum-Minimum) + Minimum",                  },                  Blip = Input { Expression = "iif( (((time+Period) % (Period+BlipLength) / Period) * (Period/BlipLength) - (Period/BlipLength)) >= 0,Maximum,Minimum)", },               },               ViewInfo = OperatorInfo { Pos = { 0, 10.15 } },               Colors = {                  TileColor = { R = 0.498039215686275, G = 0.498039215686275, B = 1 },                  TextColor = { R = 0, G = 0, B = 0 },               },               UserControls = ordered() {                  Red = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Green = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Blue = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Alpha = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Gain = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Lift = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Gamma = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Contrast = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Brightness = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Saturation = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Low = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  High = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  Direction = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  ClipBlack = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  ClipWhite = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  PreDividePostMultiply = {                     INPID_PreviewControl = "",                     IC_ControlPage = 0,                     INPID_InputControl = "",                  },                  SineWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Sine Wave",                  },                  TriangleWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Triangle Wave",                  },                  SquareWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Square Wave",                  },                  SawtoothWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Sawtooth Wave",                  },                  ParabolicSawtoothWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Parabolic Sawtooth Wave",                  },                  ReversedParabolicSawtoothWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Reversed Parabolic Sawtooth Wave",                  },                  ExponentialSawtoothWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Exponential Sawtooth Wave",                  },                  BounceWave = {                     LINKID_DataType = "Number",                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Bounce Wave",                  },                  Blip = {                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKID_DataType = "Number",                  },                  SineBlip = {                     LINKID_DataType = "Number",                     LINKS_Name = "Sine Blip",                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     INP_Default = 0,                  },                  Minimum = {                     INP_Default = 0,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKID_DataType = "Number",                  },                  Maximum = {                     INP_Default = 1,                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     LINKID_DataType = "Number",                  },                  Period = {                     INP_MinScale = 2,                     INPID_InputControl = "SliderControl",                     LINKID_DataType = "Number",                     IC_ControlPage = 0,                     INP_MaxScale = 120,                     INP_Default = 24,                  },                  BlipLength = {                     LINKID_DataType = "Number",                     INPID_InputControl = "SliderControl",                     LINKS_Name = "Blip Length",                     IC_ControlPage = 0,                     INP_MaxScale = 60,                     INP_Default = 2,                  }               }            }         },      }   },   ActiveTool = "MT_Glitch_Waves"}`

### Re: Distance between two points Posted: Tue Jan 16, 2018 12:32 am
THANKS!

so, what I was trying to build is called a "triangle wave" . Now I know it's obvious why.

The trig approach in that macro is much more elegant and simpler than my "brute force" approach.

Code: Select all
`(((int((time*n1)/n2))%2)*n2)+((time*n1)%n2)*((-1)^int((time*n1)/n2))`

where n1 is speed (time multiplier) and n2 is amplitude in space units.

Tough and probably an excess of parenthesis, but it works with fixed amplitude.

If I animate the amplitude the values go crazy... tomorrow I'll try to solve it, because the trig approach you sent me is based on perid instead of speed, and I need constant speed.

(If I can't refine my expression I'll try with the provided and animate both amplitude and period to get constant speed. Maybe with a inverse function...

This whole thing of expressions and scrpts is so powerful, but first steps are hard for self-learning, and worse if you're not good at maths. I'm not.

### Re: Distance between two points Posted: Tue Jan 16, 2018 1:07 am
deleted.

### Re: Distance between two points Posted: Tue Jan 16, 2018 2:01 am
You won't get an intelligible result from trying to animate the speed (or period). The reason for that is because a formula like this will recalculate its value based simply on the current time, not on its previous value. It's really difficult to build an expression with "memory" of what its previous value was. It's an integral calculus problem. While it's theoretically possible, the only way I know how to do it involves recalculating all previous frames on every new frame. As the playhead advances, the expression gets slower and slower.

Here's an example of the technique applied to randomly segmenting the timeline:

Code: Select all
`{   Tools = ordered() {      MT_TimeSegmenter = MacroOperator {         CtrlWZoom = false,         Inputs = ordered() {            Comments = Input { Value = "Increments a counter at randomized time intervals. \r\n\r\nMuse Tools Library, Glitch Tools Collection\r\nby Bryan Ray\r\nwww.musevfx.com", },            Segment = InstanceInput {               SourceOp = "TimeSegmenter",               Source = "Gain",               Expression = ":i=0; seg=-1; randomseed(RandomSeed); while i<=time do seg=seg+1; i=i+random(MinimumSegmentLength,MaximumSegmentLength); end; return seg",               Name = "Current Segment",               Default = 10,            },            MinimumSegmentLength = InstanceInput {               SourceOp = "TimeSegmenter",               Source = "MinimumSegmentLength",               Default = 3,            },            MaximumSegmentLength = InstanceInput {               SourceOp = "TimeSegmenter",               Source = "MaximumSegmentLength",               Default = 15,            },            RandomSeed = InstanceInput {               SourceOp = "TimeSegmenter",               Source = "RandomSeed",               Default = 0.4068323,            }         },         ViewInfo = GroupInfo { Pos = { 330, 577.5 } },         Tools = ordered() {            TimeSegmenter = BrightnessContrast {               CtrlWZoom = false,               CtrlWShown = false,               NameSet = true,               Inputs = {                  Blend = Input { Value = 0, },                  Gain = Input {                     Value = 10,                     Expression = ":i=0; seg=-1; randomseed(RandomSeed); while i<=time do seg=seg+1; i=i+random(MinimumSegmentLength,MaximumSegmentLength); end; return seg",                  },                  RandomSeed = Input { Value = 0.4068323, },               },               ViewInfo = OperatorInfo { Pos = { 0, 10.15 } },               UserControls = ordered() {                  MinimumSegmentLength = {                     INP_MaxAllowed = 1000,                     INP_Integer = true,                     INPID_InputControl = "SliderControl",                     IC_ControlPage = 0,                     INP_MaxScale = 30,                     INP_Default = 3,                     INP_MinAllowed = 0,                     LINKID_DataType = "Number",                     LINKS_Name = "Minimum Segment Length",                  },                  MaximumSegmentLength = {                     INP_MaxAllowed = 10000,                     INP_Integer = true,                     INPID_InputControl = "SliderControl",                     IC_ControlPage = 0,                     INP_MaxScale = 60,                     INP_Default = 15,                     INP_MinScale = 1,                     INP_MinAllowed = 0,                     LINKID_DataType = "Number",                     LINKS_Name = "Maximum Segment Length",                  },                  RandomSeed = {                     LINKID_DataType = "Number",                     LINKS_Name = "Random Seed",                     IC_ControlPage = 0,                     INPID_InputControl = "SliderControl",                     INP_Default = 0,                  }               }            }         },      }   },   ActiveTool = "MT_TimeSegmenter"}`

The while loop is what does the integration—it repeats the calculation over and over until i is equal to the current frame.

### Re: Distance between two points Posted: Tue Jan 16, 2018 11:58 am
Hi Bryan.

I see. Doing some tests I got it.

Animating amplitude with step in (no interpolation) reveals the problem: It works but, the moment the amplitude changes, the object jumps instantly to the place it should be if the new amplitude were active since the beginning. If you interpolate amplitude changes, the transition frames are a kind of weird high freq wave, and stabilizes when the amplitude stays constant.

I'm now trying with a different approach: Simulating a real ping-pong with a constant speed particle.

I shoot one particle with a initial velocity, and set two bouncing boxes. The particle kepps bouncing at perfectly constant speed and I can animate the separation of the boxes to change amplitude. It works perfect if the bouncing boxes move gently. If they're moving fast at the contact moment they sometimes miss the ball. And you might need to go to frame 0 and restart the particle system after changing the amplituce animation, but it's only one particle so everything runs very fast. Usable.

Great!, but now, how can I send the x coordinate of my particle to another object? I'm afraid this workaround gets me in the gates of pCustom, something I'm really scared of 