[Logic emerged] Articulation in animation
-
I am trying to figure out how to sequence the train animation so I can offset and rotate each wagon in turn around curves. I am developing it using KineticJS in 2d with the intention of using the same data and functionality via an .rb bridge to make a more dramatic display in Sketchup.
If you have Chrome or another fully HTML5 compatible browser you can see on Route_51 all the wagons follow the black loco at the same time. I just cannot figure out yet how to create the stagger. Here is a zoom screenshot to show the situation:
Here is my code for running the straight sections:
function animate(nr,path,incr,train,dirX,dirY){ var steps,offsetX,offsetY,count,a; steps = Math.round(path[nr][2] / incr); offsetX = path[nr][2]/steps; offsetY = path[nr][3]/steps; count = 0; stage.onFrame(function(frame){ layer = train[0].getLayer(); if(count < steps){ for(a=0; a<train.length; a+=1){ incrX = train[a].getX() + offsetX * -dirX; incrY = train[a].getY() - offsetY * -dirY; train[a].setX(incrX); train[a].setY(incrY); } layer.draw(); count += 1; } else{ stage.stop(); nr += 1; if(path[nr]){ animate(nr,path,incr,train,dirX,dirY); } } }); stage.start(); }
I don't seem to be able to grasp the logic (getting too old).
Any help appreciated. Thanks.
-
Don't know the exact logic, but each wagon needs to follow the car in front of it (be it loco or wagon.)
How about logically, moving the loco, then iterating the train's members ??
-
EDIT: Ok, I know you are already iterating the train...
.. I mean specifically that you must pass the preceeding car's position, to the next car.
If you wish to get more "real", each car actually has two pivot points, under the front and rear carriage assembly.
-
@dan rathbun said:
Don't know the exact logic, but each wagon needs to follow the car in front of it (be it loco or wagon.)
How about logically, moving the loco, then iterating the train's members ??
The straight runs do this - rather in each frame each wagon's x value is properly spaced behind the loco; the Y value is the same. The way I have it when the Y-value needs to be offset to take up the curve it gets applied to all. Here is where I get stuck;
Each wagon needs its own animation to follow the same path, the stagger being set by its starting position,
or
Somehow each wagon needs to know when to apply the Y offset (and rotation)
-
@dan rathbun said:
EDIT: Ok, I know you are already iterating the train...
.. I mean specifically that you must pass the preceeding car's position, to the next car.
I don't think the relationship is between wagons but between wagon and path.
@dan rathbun said:
If you wish to get more "real", each car actually has two pivot points, under the front and rear carriage assembly.
The wagons are fixed axle coal wagons 6 x 2.5m on plan; the curves are 60m radius. One purpose of the animation is analytical so the calcs have to be real even though the display maybe a bit squiffy due to the radical scaling.
-
I thought about this tonight whilst sitting on the porch watching a thunderstorm.
It seems that a track would need to be an object, with an Array inside it, whose members are vertices, representing the possible positions of cars. The number and distance between vertices would depend upon your chosen resolution.
This track object would also have a function that returns the next positional vertex for a car. The arguments to this function would be the car's current position, and a velocity. If the train was slow, the next vertex might be returned, or as the speed increases, more and more vertices would be skipped.
Think of the vertices of the track (looking down from above,) as the plotting of a mathematical function on the XY plane. The rotational direction of each car, would be the derivative of it's position. Now if they are perfect curves, that will likely simplify the math. If you know the center point of the curve, the slope of the car (it's longitudinal axis,) will be perpendicular, to the line between the position and the curve's center point.
-
As we seem to be thinking in parallel let me set out what I am doing right now to help define options.
All the x values of both straights and curves are accumulated as the path array is assembled. When the type is a curve it stores [start,finish,max Y offset] in a curve array. Later the rotIncr (horizontal rotation) will be added.
function createPath(){ var cp,t,radian,distX,distY; cp = config.pass; path = []; accX = cp.locoXYR[0]; cp.carray = [] for(a=0; a<cp.tracks.length; a+=1){ rotIncr = null; t = nset[cp.tracks[a]]; radian = t.Rotation * Math.PI / 180; distX = Math.cos(radian) * t.Length; lastAccX = accX; accX += distX; distY = 0; //curves if(t.Category === "Curve"){ switch(t.Direction){ case "Rightup"; x = -1; break; case "Leftdown"; x = -1; break; case "Rightdown"; x = 1; break; case "Leftup"; x = 1; break; } distY += t.OffsetY * x; rotIncr = t.Arc / t.Length * x; //rotIncr = incr * t.OffsetY / t.Length; cp.carray.push([Math.round(lastAccX),Math.round(accX),Math.round(distY)]); } distY += Math.sin(radian) * t.Length; distX = Math.abs(Math.round(distX)); distY = Math.abs(Math.round(distY)); path.push([t.Entry,t.Category,distX,distY,rotIncr]); } lert(cp.carray.join("<br>")); return path; }
Now doing ...
In the animator ...
Each loco/wagon's getX() is compared to the carray. If within any of the array elements start/finish, the Y incr is interpolated, the running Y value updated and the rotIncr applied.
Here is the code before doing this:
function animate(nr){ var cp,steps,offsetX,offsetY,count,a; cp = config.pass; steps = Math.round(cp.path[nr][2] / cp.incr); offsetX = cp.path[nr][2]/steps; offsetY = cp.path[nr][3]/steps; count = 0; stage = coreKJSStage(); stage.onFrame(function(frame){ if(count < steps){ for(a=0; a<cp.train.length; a+=1){ car = coreKJSShape(cp.train[a]); incrX = car.getX() + offsetX * -cp.dir[0]; incrY = car.getY() - offsetY * -cp.dir[1]; car.setX(incrX); car.setY(incrY); } KJSLayer("Trains"); count += 1; } else{ stage.stop(); nr += 1; if(cp.path[nr]){ animate(nr); } } }); stage.start(); }
I understand what you are saying about rotation, speed (increments), zooming and so on, but I just wanted to see first how to offset the cars individually.
Interested to hear what you think.
Back to the animater!
Edit GMT 10.30 + 8: doesn't work! Trying another tack on same basic idea
-
Another version, which better fits with what you say Dan (maybe), is to interpolate the real starts and finishes of path sections so that the path provides coordinates at fixed increments. The getX() of each car finds the nearest x increment and reads off its Y value.
The 14 deg (0.1 radian) arcs (curves) use 51 frames at the current settings. I cannot change the milliseconds, only the increments. Here is a nameset record showing typical data.
"10";{ "Entry";"10", "Label";"T10", "Class";"Track", "Category";"Curve", "Backlink";["Tracks"], "Keyset";"KS01", "X";72855, "Y";159891, "Radius";60000, "Rotation";-20, "Direction";"Leftdown", "Arc";0.1, "Length";18818, "OffsetY";3027 },
I am not sure and hungry!
-
It seems a certain amount of time has to pass before some kind of logic emerges.
In this case it was that each loco/wagon needed its own fully incremented path for the starts and optionally finishes to be staggered. Here is a screenshot of the train in motion with the "normal" scale view inset. Room for improvement of course especially with curve coordinates.
For the animation click New machines and follow the train link.
Thanks Dan for the background inspiration.
-
NO problem.
Chewin' on it helps. Sleeping on it helps. Brainstormin' helps.
Advertisement