Why is this interpolation not working?
Hi all,
I am writing a javascript piece of code and for some reason it is not working. The idea is: I have 9 different jit.gl.gridshapes each with a different texture.
When the function "randomize" is called, these pieces jump to a different location in space, but not suddenly, interpolating (tweeing) from the original position to the final position. These intermediate positions are calculated inside the js object and then sent to 9 different [receive] objects inside my patch.
The problem: for some reason, the intermediate positions (tween) calculated by function interpolate(c) stops at a certain moment, so for example if the object's x coordinate should travel from 2.0 to 3.0 in a time defined by the counter (which goes from 0. to 1.), then it stops calculating at 2.6 and keeps on outputting 2.6, 2.6, 2.6, 2.6....until the counter stops.
Hope I am making myself more or less clear and someone has the time to help me!
//js code//////////////////////////////////////////////////
inlets=1;
outlets=0;
var nPieces =9;
var pieces = new Array(nPieces);
var originPos = new Array(nPieces); //store actual positions, then generate new positions
var finalPos = new Array(nPieces); //store actual positions, then generate new positions
var sendObj = ["send0", "send1", "send2", "send3", "send4", "send5", "send6", "send7", "send8"];
var rScale = 5;
var counter = 0.0;
var refreshCounter = 0.01;
var interpYesNo = false;
var ready = false;
var PI = 3.141594;
function piece(x, y, z, w, h) { //pieces constructor
this.pos = [x,y, z];
this.scale = [w,h, 1.0];
this.vel = [0.0, 0.0, 0.0];
}
function setUpPieces () {
for(i=0; i
{
pieces[i] = new piece(0.0, 0.0, 0.0, 1.0, 1.0);
}
}
function randomPos () {
return(((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale));
}
function calculateNewPositions() {
//store origin and final pos
for(i=0; i
originPos[i] = pieces[i].pos;
finalPos[i] = [randomPos(), randomPos(), randomPos()];
}
ready = true; //ready to start interpolation
}
//LINEAR INTERPOLATION
function interpolation (initialPos, finalPos, time) {
return(initialPos+time*(finalPos-initialPos));
}
function interpolate(c) {
for(i=0; i
{
pieces[i].pos[0] = interpolation(originPos[i][0], finalPos[i][0], c);
pieces[i].pos[1] = interpolation(originPos[i][1], finalPos[i][1], c);
pieces[i].pos[2] = interpolation(originPos[i][2], finalPos[i][2], c);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
function randomize() {
if (interpYesNo == false) {
interpYesNo = true;
calculateNewPositions();
}
else return;
}
function updateCounter() {
if (interpYesNo == true && ready == true) //if interpolation is ON, then
{
counter += refreshCounter;
post(counter, "n");
interpolate(counter);
if (counter >=1.0)
{
interpYesNo = false;
ready = false;
counter = 0.0;
}
}
}
function bang(){
updateCounter();
}
//end js code
cool code. i would use a Task for that. did you try it?
Never heard of Tasks before, I just found a tutorial... why do you think that a task could be useful in this case?
I´m taking a look at the JS Tasks tutorial and thanks: yours was a great tip!!!
By using tasks I don´t have to depend on the bang () function to trigger the counter. Instead, the updateCounter regulates its own timing and repetitions by itself.
I still don´t know if this will solve the problem in the interpolation function. I will implement a task in this code and see if the problem is solved.
So I re-wrote the code using tasks. The problem with the interpolation is still the same, the pieces seem to "freeze" at some point and do not complete the movement from the origin to final position
//new js
inlets=1;
outlets=0;
var nPieces =9;
var pieces = new Array(nPieces);
var originPos = new Array(nPieces); //store actual positions, then generate new positions
var finalPos = new Array(nPieces); //store actual positions, then generate new positions
var sendObj = ["send0", "send1", "send2", "send3", "send4", "send5", "send6", "send7", "send8"];
var rScale = 5;
var counter = 0.0;
var refreshCounter = 0.01;
var interpYesNo = false;
var PI = 3.141594;
//TASKS
var tsk = new Task(updateCounter, this);
tsk.interval = 50; //repeats each 50 ms
function piece(x, y, z, w, h) { //pieces constructor
this.pos = [x,y, z];
this.scale = [w,h, 1.0];
this.vel = [0.0, 0.0, 0.0];
}
function setUpPieces () {
for(i=0; i
{
pieces[i] = new piece(0.0, 0.0, 0.0, 1.0, 1.0);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
function randomPos () {
return(((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale));
}
function calculateNewPositions() {
//store origin and final pos
for(i=0; i
originPos[i] = pieces[i].pos;
finalPos[i] = [randomPos(), randomPos(), randomPos()];
}
}
//LINEAR INTERPOLATION
function interpolation (initialPos, finalPos, time) {
return(initialPos+time*(finalPos-initialPos));
}
function interpolate(c) {
for(i=0; i
{
pieces[i].pos[0] = interpolation(originPos[i][0], finalPos[i][0], c);
pieces[i].pos[1] = interpolation(originPos[i][1], finalPos[i][1], c);
pieces[i].pos[2] = interpolation(originPos[i][2], finalPos[i][2], c);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
function randomize() {
if (interpYesNo == false) {
interpYesNo= true;
calculateNewPositions();
tsk.repeat(); //start task
}
}
function updateCounter() {
if(counter < 1.0)
{
counter += refreshCounter;
post(counter, "n");
interpolate(counter);
}
else
{
counter = 0.0;
interpYesNo = false;
arguments.callee.task.cancel(); //cancel the task
}
}
updateCounter.local = 1; //prevent triggering the task directly from outside the js
function stop() {
tsk.cancel();
interpYesNo = false;
}
//end js
I solved it, the problem was in the "interpolate(c)" function. I was calculating an interpolated position, and then storing it again as an initial position. So the interpolation trajectory became each time smaller and smaller...
//INCORRECT FORM
function interpolate(c) {
for(i=0; i
{
pieces[i].pos[0] = interpolation(originPos[i][0], finalPos[i][0], c);
pieces[i].pos[1] = interpolation(originPos[i][1], finalPos[i][1], c);
pieces[i].pos[2] = interpolation(originPos[i][2], finalPos[i][2], c);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
//CORRECT FORM. Just sends the interpolated values out
//and does not store them anywhere
function interpolate(c) {
for(i=0; i
{
messnamed(sendObj[i], "position",
interpolation(pieces[i].pos[0], finalPos[i][0], c),
interpolation(pieces[i].pos[1], finalPos[i][1], c),
interpolation(pieces[i].pos[2], finalPos[i][2], c));
}
}
//////////////////////////////////////////////////////////////////////////
//Complete corrected js code
inlets=1;
outlets=0;
var nPieces =9;
var pieces = new Array(nPieces);
var finalPos = new Array(nPieces); //store actual positions, then generate new positions
var sendObj = ["send0", "send1", "send2", "send3", "send4", "send5", "send6", "send7", "send8"];
var rScale = 5;
var counter = 0.0;
var refreshCounter = 0.01;
var interpYesNo = false;
var PI = 3.141594;
//TASKS
var tsk = new Task(updateCounter, this);
tsk.interval = 50; //repeats each 50 ms
function piece(x, y, z, w, h) { //pieces constructor
this.pos = [x,y, z];
this.scale = [w,h, 1.0];
this.vel = [0.0, 0.0, 0.0];
}
function setUpPieces () {
for(i=0; i
{
pieces[i] = new piece(0.0, 0.0, 0.0, 1.0, 1.0);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
function randomPos () {
return(((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale));
}
function calculateNewPositions() {
//store origin and final pos
for(i=0; i
//originPos[i] = pieces[i].pos;//DELETE THIS LINE
finalPos[i] = [randomPos(), randomPos(), randomPos()];
}
}
//LINEAR INTERPOLATION
function interpolation (initialPos, finalPos, time) {
return(initialPos+time*(finalPos-initialPos));
}
for(i=0; i
{
messnamed(sendObj[i], "position",
interpolation(pieces[i].pos[0], finalPos[i][0], c),
interpolation(pieces[i].pos[1], finalPos[i][1], c),
interpolation(pieces[i].pos[2], finalPos[i][2], c));
}
}
function randomize() {
if (interpYesNo == false) {
interpYesNo= true;
calculateNewPositions();
tsk.repeat(); //start task
}
}
function updateCounter() {
if(counter < 1.0)
{
counter += refreshCounter;
post(counter, "n");
interpolate(counter);
}
else
{
counter = 0.0;
interpYesNo = false;
for(i = 0; i
{
pieces[i].pos = finalPos[i]; //STORE FINAL POSITION AS INITIAL POSITION }
arguments.callee.task.cancel(); //cancel the task
}
}
updateCounter.local = 1; //prevent triggering the task directly from outside the js
function stop() {
tsk.cancel();
interpYesNo = false;
}
//end js code
cool! nice one. maybe i will steal your code now. ha ha.
Hi again
Still working on interpolation. Now that simple interpolation works, I want my object to grow and shrink in a back and forth movement "like a boomerang". Each time I call my function, I want to "launch it" once.
In this case, origin and final scaling are the same.
I have tried using a cubic interpolation but it does not work properly. What formula should I use for this?
Thanks in advance.....
//code
//COSINE INTERPOLATION
function cosineInterpolation(initialPos, finalPos, time)
{
var mu2 = (1-Math.cos(time*PI))/2;
return(initialPos*(1-mu2)+finalPos*mu2);
}
//CUBIC INTERPOLATION
function cubicInterpolation(y0, y1, y2, y3,time)
{
var a0,a1,a2,a3,time2;
time2 = time*time;
a0 = y3 - y2 - y0 + y1;
a1 = y0 - y1 - a0;
a2 = y2 - y0;
a3 = y1;
return(a0*time*time2+a1*time2+a2*time+a3);
}
//MY FUNCTION
function interpolateParabola(c) {
messnamed(sendObj[id], "scale", cubicInterpolation(p.scale[0],
p.scale[0]*Xscale, p.scale[0]*Xscale, p.scale[0], c),
p.scale[1],
p.scale[2]);
}
//end js code
BTW check out this web by Paul Bourke, he describes the several interpolation methods and includes C++ functions
Got it!
I changed my approach. Instead of taking a counter from 0.0 to 1.0 as a time value for the interpolation formula, I take the number of iterations of the task.
//js code
var parab = new Task(interpolateParabola, this);
parab.interval = 10;
glob.maxIterations = 50;
function startParabola() {
if(parabYesNo == false) {
parabYesNo = true;
parab.repeat();
}
}
function interpolateParabola() {
mappedIter = map_range(iter, 0, glob.maxIterations, 0.0, 1.0);
if(iter < glob.maxIterations/2)
{
messnamed(sendObj[id], "scale", cosineInterpolation(p.scale[0],
p.scale[0]*Xscale, mappedIter),
p.scale[1],
p.scale[2]);
}
else
{
messnamed(sendObj[id], "scale", cosineInterpolation(p.scale[0]*Xscale, p.scale[0], mappedIter),
p.scale[1],
p.scale[2]);
}
iter++;
if(iter == glob.maxIterations) {
parabYesNo = false;
iter = 0;
arguments.callee.task.cancel(); //cancel the task
}
}
//end js code
function stopParabola() {
if(parab.running == true) {
parab.cancel();
parabYesNo = false;
}
}
thanks a lot for posting back!