# 2D Shape extruder

## Recommended Posts

Hi people,

Would you buy a 2D Shape extruder ? mmh ? along a curve ?

Say, you have a 2D Shape defined by an array of Vector3 :

`  // 2D shape  var shape = [    new BABYLON.Vector3(0 , 1, 0),    new BABYLON.Vector3(0, 0, 1),    new BABYLON.Vector3(0, -1, 0),    new BABYLON.Vector3(0, 0, -1)  ];  shape.push(shape[0]);`

Ok ?

Here it is : http://www.babylonjs-playground.com/#GC5NU

Yes, it's in the yOz plane, so rotate to see it please. I scaled x3 because we have elder readers here

Now, here is a simple piece of sinusoidal curve constructed with 20 points : http://www.babylonjs-playground.com/#GC5NU#1

Still ok ? nothing complicated

What I propose is the way to construct a new mesh by extruding the shape along this curve this way : http://www.babylonjs-playground.com/#GC5NU#2

So this would give this final mesh : http://www.babylonjs-playground.com/#GC5NU#3

The same with material : http://www.babylonjs-playground.com/#GC5NU#4

not smooth, ok, but only 20 point path, you know.

Ok, I know it just looks like a tube with a squared section for now, so nothing spectacular.

Let's add some Vector3 to our initial 2D shape (rotate please) : http://www.babylonjs-playground.com/#GC5NU#5

Extrusion : http://www.babylonjs-playground.com/#GC5NU#6

What if I get a 3D shape : http://www.babylonjs-playground.com/#GC5NU#7

Extrusion : http://www.babylonjs-playground.com/#GC5NU#8  Works... almost, I know why ... because extrusion is based on vector cross product with tangents and these tangents are colinear to some vexter of this 3D shape.

Anyway, it's not intended to extrude 3D shapes initially. Maybe would we construct the 2D shape with Vector2 only then.

Let's know imagine I could add, like for the Tube mesh :

- a scale parameter... to scale the initial 2D shape

- an optional custom scale function  : the ability to change scaling in function of point position or distance from the begining of the path

- an optional angle step : the shape would then rotate this step each iteration

- an optional  custom angle function : the ability to change rotation in function of point position or distance from the begining again

I could also add the possibility to put off balance the 2D Shape so the axis for the path could be elsewhere than in its center. Don't know if I am clear... to pick the axis not in the center of the start, but on the left, on a branch, or anywhere else.

So would you buy this new feature ?

For you only, I'll make it free before end of March !

It won't cost a lot to me as the extruder logic is only  10 LOC currently  :

`  // Extruder  var path3D = new BABYLON.Path3D(curve);  var tangents = path3D.getTangents();  var shapePaths = [];  for (var i = 0; i < curve.length; i++) {    var shapePath = [];    for (var p = 0; p < shape.length; p++) {      var rotated = BABYLON.Vector3.Cross(tangents[i].normalize(), shape[p]).scale(3);      rotated = rotated.add(curve[i]);      shapePath.push(rotated);    }    shapePaths.push(shapePath);  }  var extruded = BABYLON.Mesh.CreateRibbon("extruded", shapePaths, false, false, 0, scene);`

Ok, extruding a star along a sinusoid is quite useless, I agree.

But I imagine the possibility to slightly extrude shapes (ovals on faces, cropped image polygons on people, etc) on a picture could give a good 3D effect : select people and things that are front line, crop them, extrude them slightly and apply then the picture as a texture to the extruded mesh.

See what I mean ? bas-relief

Maybe other usages, don't know...

Just know it's not that expensive to implement

I personaly don't need it, but I know how to code it now.

So people, please let me know if I should dive back into TS waters.

##### Share on other sites

Oopss

It seems I spoke too fast (once again )

My extrudor doesn't work well if I align tangents with the yOz plane, the one in wich the shape is currently defined.

It really needs something clever than just a vector cross product to apply the 2D Model in the plane orthogonal to each path tangent.

Any idea how to transform (to pivot) 2D coordinates in another given plane coordinates ? something to do with pivotMatrix maybe ?

I've got to check (if documented)

----

EDIT : So I don't know yet how to do.

Kind of boaster

##### Share on other sites

We dont want to hear about shortfalls!    Now go edit that last post to be something positive, or at least spin the misery in a positive way, and then I'll adjust this comment, too.     There's going to be small explosions in Professor Ribbonator's lab, its to be expected.  Just don't tell anyone, because OSHA and our insurance company will be ALL OVER US!!!  heh

Excellent 1st post, by the way.  Friggin' tutorial.  Cooooool.

##### Share on other sites

(huuu... I wish I work in a lab, but it's not the case... used to be however)

Any link about BJS tools to rotate pivot a cartesian orthogonal system to another one (my triplet) is welcome ... I won't find  this by myself in all those doc/forum strata

What I need to solve :

I have shape coordinates in the world reference. They are on a plane (can be choosen arbitrary).

I know another plane defined by a point in space and a vector orthogonal to this plane, called the tangent (to the curve). I even have normal and binormal, so I have an orthogonal triplet with this former point for origin.

I would like to report/pivot/rotate (whatever the right term) the initial shape (or plane) onto the plane defined by the point and the tangent... (World origin to this point) and then know the shape new rotated/pivoted coordinates in the World reference.

Is there a BJS method for this ?

I could of course make rotation computation with cos/sin, angles... but I dislike to reinvent the wheel or re-do things already done (often worse) and it would explode my 10 LOC ratio

##### Share on other sites

I don't know if this is pertinent, but couldn't you do all the ring transforms... in a separate pass along the tube?  Build straight tube, then run a FOR-loop thru the rings... "massaging" them.    Each iteration... clone the previous ring's matrix, transform ring points brutally, index++, rinse, repeat.

##### Share on other sites

it's quite this actually !

The path3D object computes at each point a triplet (tangent, normal, binormal), well, a cartesian system. One per path point.

What I need is to "apply" the 2D shape on the local normal/binormal plane (originated at the path point) and get its new coordinates in the World reference

I do iterate from a point to another on the path, so from a cartesian system to another.

If I am able to apply the 2D shape in a first cartesian system, it's quite easy to go to the next one. I guess I can master this.

My  problem is only to initially transform my 2D shape defined in a user-friendly plane (x0y in World reference for instance) in the same 2D shape then defined in the first normal/binormal plane on the first path point.

And get the transformed 2D shape World reference new coordinates.

I saw somewhere there was something about pivotMatrix or something like that.

Don't know where... neither if it's the right tool, neither how to use it ...

I just believe (arff, faith) there should be such a tool in BJS

##### Share on other sites

I have to admit that you ask is not clear to me:) can you explain it with some examples? perhaps example of code you would have love to find?

##### Share on other sites

TILT ... !

Sometimes let you just focus on basic domestic tasks for a while and your brain continues the job in backgroung without the pollution of your conscience  And it works !

Ok, I thought about some complex matrix pivot to pass from a user defined 2D shape in his user friendly plane (we really take of users here  ) to my first cartesian system on the path...

Well, I think there's a very very simple way to do it actually.

If my 2D shape is, say, in the World reference xOy plane, I just have to decide that my path point P is O (originà in the path local cartesian system, the normal vector is x-axis and the binormal vector is y-axis.

So I just have to multiply each 2D shape initial coordinate by the normal and binormal normalized vector and add them to the P vector... I should then get the 2D shape, "applied" to the normal-P-binormal plane, coordinates in the World reference, nope ?

I'll check tomorrow

##### Share on other sites

@DK :

You see my first post :

I just want to set a 2D shape (http://www.babylonjs-playground.com/#GC5NU , it's yOz here) designed by a user in xOy, for example, onto the plane defined by the first point of the path and its orthogonal vector and then know this pivoted 2D shape world reference coordinates.

http://www.babylonjs-playground.com/#GC5NU#2

here, I was using the cross product, but it was wrong, just a particuliar case.

I know each point of the path coordinates. I know a triplet of orthogonal normalized vectors on each point too.

(and I just can't explain right these simple things in good english !)

Unless you have a smart good strong fast idea, I'll test mine tomorrow

##### Share on other sites

Let's test yours:)

##### Share on other sites

Seems to work !

Let's change curve orientation : http://www.babylonjs-playground.com/#GC5NU#10

Still works

Let's twist it hard : http://www.babylonjs-playground.com/#GC5NU#11

Still works

Let's try a 3D shape instead : http://www.babylonjs-playground.com/#GC5NU#12

ribbonized : http://www.babylonjs-playground.com/#GC5NU#13

Ok, works... even if this very example is not that spectacular

What could  we do more useful with this feature so ?

Well, let's get another 2D Shape, unclosed this time (please rotate) : http://www.babylonjs-playground.com/#GC5NU#14

simple, only 7 points, symetric, hand made, scaled x4 (for our old readers, remember )

Now, let's give the curve 60 points instead of only 20, so the path will be smoother :

`var curve = curvePoints(40, 60);`

http://www.babylonjs-playground.com/#GC5NU#15

Extrusion sir : http://www.babylonjs-playground.com/#GC5NU#16

Starts to look to something better

mmh... remember, there is a ribbon under the hood, so I can closePath it, just changing a parameter from false to true : http://www.babylonjs-playground.com/#GC5NU#17

strange snake, isn't it ?

We can then play with the curve, just changing some factors, adding it more points too : http://www.babylonjs-playground.com/#GC5NU#19

Minor changes have big effects : http://www.babylonjs-playground.com/#GC5NU#20

If you don't like to play with cos/sin, you ever can set your curve easily by hand of course :

`  var curve = [    new BABYLON.Vector3(-10, 10, -10),    new BABYLON.Vector3(10, -10, 10)  ];`

an ultra-basic curve : a starting point and an ending point only !

http://www.babylonjs-playground.com/#GC5NU#21

##### Share on other sites

More seriously, what I propose is a set of two functions, a basic one and an advanced one :

`BABYLON.Mesh.ExtrudeShape(name, shape, path, scale, rotation, scene)`

and

`BABYLON.Mesh.CustomExtrudeShape(name, shape, path, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, scene)`

for both :

• name : the mesh name
• shape : the 2D (or 3D) shape as an array of Vector3... the main 2D plane to design it could be xOy arbitrarily
• path : the path to extrude the shape along as an array of successive Vector3
• scene : the current scene

for the basic method :

• scale : the value to scale the shape, default 1
• rotation : the rotation step to apply to the shape on each path point iteration, default 0

for the Custom method :

• scaleFunction : a custom js function returning a scale value from (i, distance) input parameters,
• rotationFunction : a custom js function returning a rotation angle from (i, distance) input parameters,
• ribbonCloseArray : boolean, the underlying ribbon closeArray parameter, default false,
• ribbonClosePath : boolean, the underlying ribbon closePath parameter, default false

where (i, distance) are the position i of the current iterated point in the path and its distance from the begining of the path

and where xxxFunction() is called on each path point when iterating on the path, like for the Tube mesh.

It seems very complex said like this, but it's quite easy to use actually.

And as I said in the first post, it's quite light to code too

the final working extrudator code is only here :

`  // Extruder  var path3D = new BABYLON.Path3D(curve);  var tangents = path3D.getTangents();  var normals = path3D.getNormals();  var binormals = path3D.getBinormals();  var shapePaths = [];  for (var i = 0; i < curve.length; i++) {    var shapePath = [];    for (var p = 0; p < shape.length; p++) {      var rotated = ( (tangents[i].scale(shape[p].x)).add(normals[i].scale(shape[p].y)).add(binormals[i].scale(shape[p].z)) ).scale(4).add(curve[i]);      shapePath.push(rotated);    }  }  var extruded = BABYLON.Mesh.CreateRibbon("extrude", shapePaths, false, false, 0, scene);`

So people do you want this feature in BJS ?

I do!

##### Share on other sites

One vote !

just waiting for DK's approval...

just won't code in TS + github stuff for nothing

##### Share on other sites

Ok, it's quite ready to be ported to TS

Last EXTRUDATOR marketing !

Go back to our curve. Now, I want length 40 and 200 points (l 37) :

`var curve = curvePoints(40, 200);`

http://www.babylonjs-playground.com/#25BCFS

Ol'good sinus !

I keep my former unclosed 7 point shape also.

From now everything happens at line 100 :

`var extruded = extrude(shape, curve, scale, rotation, myScalingFunction, myRotationFunction, rbCA, rbCP, custom );`

This is not the wanted public final signature here, just some js tool before I port it right to TS.

The last parameter is to be set if I want this method to behave as basic (false) or as custom (true).

Let's stay with custom = false.

http://www.babylonjs-playground.com/#25BCFS#1

Ok, I retrieve my kinda snake

Let's closePath its underlying ribbon (rbCP = true)  : http://www.babylonjs-playground.com/#25BCFS#2

Cool, works.

Change scale to 8 : http://www.babylonjs-playground.com/#25BCFS#3

Funny ! a fat snake... boa ?

Let's go back to scale = 2 and no ribbon closePath, but let's add some rotation of PI / 12 : http://www.babylonjs-playground.com/#25BCFS#4

<singing>Let's twist again like we did last summer </singing>

Until now, I was in basic mode only, just setting scale or rotation fixed values. Quite complex generated shape but still easy to do, nope ?

Let's go in advanced mode now, custom = true (this won't be like this in BJS, I'll give two different methods with different few arguments) : http://www.babylonjs-playground.com/#25BCFS#5

Now the scale and rotation parameters are ignored.

huuu.. wait, nothing changed ?

Actually no in the rendering.

I passed instead two custom functions  : myScaling and myRotation. But they currently return the same fixed values than before (l 86) :

`        // custom scale function        var myScaling = function(i, distance) {            var scale = 2;            //var scale = Math.cos(distance / 40) * 8;            return scale;        }                // custom rotation function        var myRotation = function(i, distance) {            var rotation = Math.PI / 12;            //var rotation = distance / 400 * Math.PI / 3;            return rotation;        } `

Let's just change the myScale function so it returns now a scale value according to the distance :

http://www.babylonjs-playground.com/#25BCFS#6

As you can see the shape size changes in function of the distance from the curve begining.

Now let's set back the scale to 2, but change the myRotation returned value according to the distance :

http://www.babylonjs-playground.com/#25BCFS#7

The nearest of the path end, the more rotated.

Let's know activate both custom functions at once : http://www.babylonjs-playground.com/#25BCFS#8

Quite complex twisted shape, nope ? and only one command line   (and two custom functions, ok, I agree)

Finally, let's just change some factors here or there, closePath the ribbon and slide the texture : http://www.babylonjs-playground.com/#25BCFS#9

Totally useless

But nice and easy to do.

##### Share on other sites

Could you please let us know what assets are available in the textures web folder please ?

##### Share on other sites

I was wondering, if I could ask a favor?  I need a string of the french & german vowels posted.  I want put these characters in fontgen.blend via clipboard.  I can then start to push parts of my Dialog system.

I can also push Font2D.js & Font3D.js, since I have broken these out.

On the extrusion subject, I ended up generating mesh letters which were 1 unit deep.  This way, setting letter.scaling.z is essentially setting the depth.

While I would like to finish Dialog system in about a week, you can still use fontgen.blend to make single mesh signs.  They can be exported using TOB to source code, or a .babylon with the offical exporter.  With that "A" selected, switch to edit mode, then type what you want with CR's if you want.  ALT-P then generates a sign instead of a font.

The Dialog systems Panel object fully written & in debug.  Panels can:

• contain sub-Panels
• layed out horizontal & vertical
• organize their sub-panel Left-Top, Center, Right-Bottom
• specify stretch to specify which sub-panels occupy any extra space.
• Top Level panels can be organized in a stack.
• Right now the only control is button.

What it looks like right now:

##### Share on other sites

You need french accentued voyels ?

àâä

éèêë

î ï

ô

ùûü

I don't think I forget somes... pffiiuuu, didn't realize there were so many

##### Share on other sites

Thanks worked, but I need upper case versions too.  Think you got german umlauts, unless there is an o umlaut too.  There is also german ss thing.

The 72 character Font3D.js (not counting those you just gave me) after uglification is 576 kb, and 2D is 176 kb.  Not really bad for 72 meshes, but a waste if you do not plan to use.  This is why I put fonts in separate files.

FYI, only the chars you use are instanced.  If you use them more than once, like "o" & "s" above, clones are made.

##### Share on other sites

É

È

Ê

Ë

Ç

ç

Ñ

ß

Ä

Á

À

Â

Æ

æ

Ö

Ô

Ü

Û

ø

Ø

some aren't french, but I gave them

##### Share on other sites

I'm wondering if is worth to add the custom function two more parameters :

- axisOffset, to offset the extrude axis

- initialAngle, the initial rotation angle to be given to the shape, whatever it rotates or not afterwards

It could be useful, but it would make the function signature heavier whereas the user could rotate and offset its shape by himself before passing it to the function. This is what I did in the playground example : my 7 point shape is offset, it's not centered on the system coordinate origin.

So I will probably forget these two extra parameters unless someone's good argument.

@DK :

There is one vote and I can do it with only 30 JS LOC for both basic/advanced function (only 30, not 30+30)  as shown in the playground. The same feature exists in ThreeJS too, but I won't tell you how complex easy it is to instanciate  .

So do you agree for a PR with this feature ?

##### Share on other sites

and the German "sz" not to forget: ß

##### Share on other sites

Boy, there sure is a bunch of "extruding" going-on here.  When I was in the U.S. Air Force (9 yrs), stationed in South Korea, I worked with extrusion quite often during night-time hours... and...  umm...  nevermind.

These extruders sure talk funny.

"Orthogonal".  Wasn't that a Hanna Barbara cartoon character?  A giraffe, I believe.

How's that for a worthless comment amidst a very interesting topic?  I did well, eh?  I give it AT LEAST a level-8 worthlessness rating.  Right?

Jerome set a new record of 12 playgrounds in a single post!  WOW!  And then he followed it up with a 9-banger!  Way to work that puppy, J-doggy!

JC... that "Gosh, I almost run!" pic/modeling is nice nice nice!!  Can you get me a vertices count on that?  thx.

##### Share on other sites

(for HB cartoon characters and SK nights  )

Someone here counting number of links per post ?!  Waaaoww

<g33k mode>

Maybe should I hack something to automatize this kind of counting by code ?

</mode>

huuu, do you count emoticons also   ?

Thank you for the 8-worthlessness rating (btw, what's is the scale ? 10 ? 700 ? 10E32 ? )

I'll try to meet the absolutely useless challenge soon to extrude a SH along a Möbius ribbon.

Yeeaahh, beat this, poor torus knot !

Well, if DK agrees, I'll attempt to do a PR monday ...

##### Share on other sites

No, no, the worthlessness rating is the value of MY post.  I didn't give any useful information, I didn't ask any pertinent questions, and I was barely on-subject at all.  (I'm SO proud)

You guys are doing great!  I LOVE the 12-PG posts and similar posts.  LOVE it!!

It's my attempts at comedy that are not doing so well.

You guys... don't change a thing.  I love what you guys are doing.  Again, the "worthless" was about MY post.  Your posts are excellent.  Extruding is VERY cool and quite useful.

I'm trying to figure out where the term "splines" used in 3DMax... gets involved with what you guys are doing.  Is the 2D shape that extruding works-upon... called a spline?  Sometimes?  Always?  Rarely?  I'll go web-reading.

## 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.