# SOLVED: Path in the shape of Infinity Symbol?

## Recommended Posts

Hello,

Does anyone know how to create a path or lines, in a closed loop, in the shape of an Infinity Symbol?

I am pretty sure I saw one in the playground, but cannot find it now.

For example: Gerono OR Bernoulli:

The Parameterization is said to be with the following equation:

``````x = cos(t);
y = sin(2*t) / 2;``````

I ran into a few errors trying to populate it on the first quick attempt....

Any advice on how to populate Gerono parameterization into the following track (editPoints)?

var track = BABYLON.MeshBuilder.CreateLines('track', {points: editPoints}, scene);

##### Share on other sites

Would have appreciated seeing a PG of your first attempt as more than likely it was pretty close to this https://www.babylonjs-playground.com/#3NYWX5#2 and just needed a bit of tweaking .

##### Share on other sites

@JohnK and @bulisor ... elegant!

Gerono and Bernoulli? Wow... extra-credit. Can't wait to learn...

Attempted algorithm missing this part:

t < 2 * Math.PI; t += Math.PI / 36

Oh! Oh, wow... gets it now, thanks!

Far better than "lets draw infinity" attempt (with editable paths).

Path-Editing holds secondary use ...

JohnK, playground (PBTs) in progress...

... afalcon on a vector.

[thanks again].

##### Share on other sites

Intriguing extension...to this awesome math.

How to govern the speed of the animated cube?

Guesses to follow.... . #1 increase number of points, OR drag the frame-rate... but there has to be a better way.

What is the most elegant and performant way to govern the speed of the animated box?

After that, solutions available on Motion-Path ORIENTATION (using LookAt) and ROLL on curve.

Thx:

##### Share on other sites

TWEEN between curve points...?

<testing>

Looks deeper into those PATH points...

A nice function for adding editable points to each curve vertex:

``````
/**********************************SHOW-EDIT-NODES*****************************/
// Example:  showEditNodes(points,{type:'box', size:0.25})
var showEditNodes = function (points, config){
var numNodes = points.length;
var editType = config.type || "box";
var editSize = config.size || 1;
var editNode;
var greenMat = new BABYLON.StandardMaterial("green1", scene);
greenMat.diffuseColor = new BABYLON.Color3(0, 1, 0);
var redMat = new BABYLON.StandardMaterial("red1", scene);
redMat.diffuseColor = new BABYLON.Color3(1, 0, 0);
var blueMat = new BABYLON.StandardMaterial("blue1", scene);
blueMat.diffuseColor = new BABYLON.Color3(0, 0, 1);

for (var i=0; i < numNodes; i++){
if(editType==='box'){
editNode = BABYLON.Mesh.CreateBox("cube" + i, 0.25, scene);
}else if(editType==='sphere'){
// Parameters: name, subdivs, size, scene
editNode = BABYLON.Mesh.CreateSphere("editNode"+i, 1, 0.75, scene);
}
//position-editNodes.
editNode.position = points[i];
//init-edit-state-.
editNode.actionManager = new BABYLON.ActionManager(scene);
editNode.editMode = "none";
editNode.vectorIndex = i;

editNode.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, function (evt) {
var eNode = evt.meshUnderPointer;
if(eNode.editMode === 'none' ){
eNode.material = greenMat;
eNode.editMode='green'
selectedEditNodes.push(eNode);
}else if(eNode.editMode === 'green' ){
eNode.material = blueMat;
eNode.editMode='blue'
}else  if(eNode.editMode === 'blue' ){
eNode.material = redMat;
eNode.editMode='red'
}else  if(eNode.editMode === 'red' ){
eNode.material = null;
eNode.editMode='none'
}
if(eNode.editMode!="none"){
displayMeshAxis(eNode, false)
} else {
displayMeshAxis(eNode, true)
var remove = selectedEditNodes.indexOf(eNode)
//selectedEditNodes.splice(remove,1)
}

}));

}
}

``````

Happy to provide displayMeshAxis and the events that edit nodes if you'd like...

##### Share on other sites

SPEED Study...

Thinking about a FrameGovernor... for Christmas.

Going to use it for ... rays. Not so good for animating movements (while it does slow things down, so tried it):

``````                var index = 0;
var biFrameGovernor = 0;
scene.registerBeforeRender(function () {
biFrameGovernor++;
if(!(biFrameGovernor % 2)){ //animate on even only.
zapbotMesh1.position = points[index];
index = (index == points.length-1)?0:index+1;
}
});``````

Slowed it down ... and it does not approximate time well.

Which is where Interpolation is good.

My brain still does not get interpolateAllThingsMethod() could someone explain?

So ... necessity to use TWEEN.

I like it. Can that not be taboo pls? Thx!

Anyway we will see if it even works...

##### Share on other sites

IT WORKED:

/******************************RECURSIVE-TRACK-TWEEN****************************************/
//    <!--TWEENJS-->
//    <script src="../../../lib/tweenjs/Tween.js"></script>
//    <script src="../../../lib/tweenjs/RequestAnimationFrame.js"></script>
/**************************************-------------****************************************/

``````                /******************************RECURSIVE-TRACK-TWEEN****************************************/
var trackIndex = 1;
var pathTargetOrb = BABYLON.Mesh.CreateSphere("sphere", 14, 1, scene);
pathTargetOrb.position= new BABYLON.Vector3(pathTargetOrb.position.x, pathTargetOrb.position.y, pathTargetOrb.position.z);
var speedGovernor = 100;
var recursiveTrackTween = function() {
var targetPoint = points[trackIndex]
var currentPoint = { x:pathTargetOrb.position.x, y: pathTargetOrb.position.y, z:pathTargetOrb.position.z };
var pathTween = new TWEEN.Tween( currentPoint ).to( { x: targetPoint.x, y: targetPoint.y, z:targetPoint.z }, speedGovernor ).onUpdate( function() {
pathTargetOrb.position.x=this.x;
pathTargetOrb.position.z=this.z;
pathTargetOrb.position.y=this.y;
}).onComplete(function() {
trackIndex = (trackIndex < points.length-2) ? trackIndex+1 : 0; //loop the track.  3 magic number because extra nodes in infinity loop...
recursiveTrackTween();
});
pathTween.start();
}
recursiveTrackTween();
/******************************RECURSIVE-TRACK-TWEEN****************************************/``````

This makes for a buttery smooth 60fps orbit around the infinity symbol points[] curve path... at any speed --> just adjust the speedGovernor!

aFalcon is terrible at playgrounds... sorry!

##### Share on other sites

Hi @Arte that code above ... the EditNodes function... is what I've been (also) working on for you.

There was a difference when applying to your playground...

Above is for editing a Curve, also converted from Ribbon, but has not been applied to MeshBuilder (yet)...

It is really fun (easy) to use... quad-state click-editor!

Tons of potential!

Sorry I seem to have problems with playgrounds.

L8r.

##### Share on other sites

I’m keeping eye on it.

##### Share on other sites

Cool @Arte, I'll be back on that code in a few days... just shot out of an animation-cannon... will give you a ping... when something lands in the dirt!

##### Share on other sites

11 hours ago, aFalcon said:

aFalcon is terrible at playgrounds... sorry!

But we love playgrounds

##### Share on other sites

Mr. G! @MarianG Yes I love playgrounds as well...

Planning sprint of writing documentation with playground based tutorials.

CURRENT-EXAMPLES (eventually for playground & doc):

Fake-Physics of a character orbiting the Infinity Path (you helped with, thank you):

#1 PATH-ORIENTATION, then #2 ROLL.

PATH-ORIENTATION:

SOLUTION: lookAt next index vertex in the path...

``````            var pathTargetOrb;
var recursiveTrackTween;
var createInfinityLoops = function(){

//track Gerono
var points = [];

for(var t = 0; t < 2 * Math.PI; t += Math.PI / 36) {
scale = 80 / ( 3 - Math.cos(2 * t));
points.push(new BABYLON.Vector3(scale * Math.cos(t), 0, scale * Math.sin(2 * t)/2));
}

points.push(points[0]);

var trackG = BABYLON.MeshBuilder.CreateLines('trackG', {points: points}, scene);
trackG.position.y = -1.2;

//track Bernoulli
var points = [];
var pathSubdivisions = 180;

// for(var t = 0; t < 2 * Math.PI; t += Math.PI / 36) {
for(var t = 0; t < 2 * Math.PI; t += Math.PI / pathSubdivisions) { //subdivisions! less is faster more jumpy, more is slower and smoother.
scale = 50 / ( 3 - Math.cos(2 * t));
points.push(new BABYLON.Vector3(scale * Math.cos(t), 3, scale * Math.sin(2 * t)/2));
}

points.push(points[0]);

var track = BABYLON.MeshBuilder.CreateLines('track', {points: points}, scene);
var abox = BABYLON.Mesh.CreateBox("box", 6.0, scene);

//SHOW-VERTICES-ON-PATH-.
// showEditNodes(points,{type:'box', size:0.25})

/******************************RECURSIVE-TRACK-TWEEN****************************************/
var trackIndex = 1;
pathTargetOrb = BABYLON.Mesh.CreateSphere("sphere", 14, 1, scene);
pathTargetOrb.position= new BABYLON.Vector3(pathTargetOrb.position.x, pathTargetOrb.position.y, pathTargetOrb.position.z);
var speedGovernor = 10; //this needs to be balanced with path-subdivisions - to get a smooth and fast speed!
recursiveTrackTween = function() {
//ANIMATE-ZAPBOT-.
var zapTargetPoint = points[trackIndex]
var zapCurrentPoint = { x:abox.position.x, y: abox.position.y, z:abox.position.z };
var pathTween = new TWEEN.Tween( zapCurrentPoint ).to( { x: zapTargetPoint.x, y: zapTargetPoint.y, z:zapTargetPoint.z }, speedGovernor ).onUpdate( function() {
abox.position.x=this.x;
abox.position.z=this.z;
}).onComplete(function() {
trackIndex = (trackIndex < points.length-2) ? trackIndex+1 : 0; //loop the track.  2 magic number because extra nodes in infinity loop...
abox.lookAt(points[trackIndex+1]); //<--ORIENTATION: to PATH.
recursiveTrackTween();
});
pathTween.start();
}
/******************************RECURSIVE-TRACK-TWEEN****************************************/
}
``````

(playground eventual).

Also --> this includes a neat optimization for SPEED STUDY:

- 1) check out the first part named pathSubdivisions. It is how many vertices subdivide the entire symbol.

This is important because: less is FASTER (but more jumpy around curve with on lookAt), and more subdivisions is SLOWER (and more smooth, turning corners)!

- 2) the speed then can be adjusted to match the smoothness with the speedGovernor.

#2 ROLL on curve (calculate angle among points...)

QUESTION: What is the best way to detect angle on 3 points?

RE-STATED: How to take 3 points from Infinity Path and detect if it is convex or concave?

<looking>

...

##### Share on other sites

#2 - How to Detect Convex and Concave on a Path?

UPDATE:  detecting angle was not enough because left angle was the same as right angle. Needed something different -> found this:

Above is a clockwise test of the mathematical function.

It might work...

##### Share on other sites

SUCCESS! It worked...

Detecting Motion Path Convex and Concave Curves and then adding ROLL rotation as the character Corners:

``````                /******************************RECURSIVE-MOTION-PATH-TWEEN****************************************/
var trackIndex = 1;
pathTargetOrb = BABYLON.Mesh.CreateSphere("sphere", 14, 1, scene);
pathTargetOrb.position= new BABYLON.Vector3(pathTargetOrb.position.x, pathTargetOrb.position.y, pathTargetOrb.position.z);
var speedGovernor = 10; //this needs to be balanced with path-subdivisions - to get a smooth and fast speed!
recursiveTrackTween = function() {
//ANIMATE-ZAPBOT-.
var zapTargetPoint = points[trackIndex]
var zapCurrentPoint = { x:zapbotMesh1.position.x, y: zapbotMesh1.position.y, z:zapbotMesh1.position.z };
var pathTween = new TWEEN.Tween( zapCurrentPoint ).to( { x: zapTargetPoint.x, y: zapTargetPoint.y, z:zapTargetPoint.z }, speedGovernor ).onUpdate( function() {
zapbotMesh1.position.x=this.x;
zapbotMesh1.position.z=this.z;
}).onComplete(function() {
trackIndex = (trackIndex < points.length-2) ? trackIndex+1 : 0; //loop the track.  2 magic number because extra nodes in infinity loop...
//ORIENTATION: to PATH.
zapbotMesh1.lookAt(points[trackIndex+1]);
//ROLL: tilt cornering.
var tilt = convexConcave(points[trackIndex],points[trackIndex+1])
if(tilt < 3.14 && tilt > 3.130){ //Right turn.
zapbotMesh1.rotation.z = 0.1;
} else if (tilt < 3.130 && tilt > 2){ //Right turn.
zapbotMesh1.rotation.z = 0.2;
} else if (tilt > -3.14 && tilt < -3.130){ //Left turn.
zapbotMesh1.rotation.z = -0.1;
} else if (tilt > -3.130 && tilt < -2){ //Left turn.
zapbotMesh1.rotation.z = -0.2;
} else {
zapbotMesh1.rotation.z = 0;
}
recursiveTrackTween();
});
pathTween.start();
}
/******************************RECURSIVE-MOTION-PATH-TWEEN****************************************/

// convex > 0, concave < 0, backward = 0, fwd = -3.14
function convexConcave (nextV, currentV) {
return ((Math.atan2(nextV.x, nextV.z) - Math.atan2(currentV.x, currentV.z) + Math.PI * 2) % (Math.PI * 2)) - Math.PI;
}``````

The convexConcave method detects which way the character is turning, and applies (gradual) ROLL rotation.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×