Per Cylinder or Per Face colors of a Cylinder Tube

Is there any way to set the per cylinder or per face colors in a cylinder Tube? I need this capability for fast rendering of a Tube which consists of potentially hundreds of cylinders, each with a different radius. I want the ability to change the color of each cylinder or some faces of a cylinder.

I could have built the cylinders individually, each with its own colors, and then merge them into a mesh (that represents my Tube), but the rendering speed is too slow compared to a single built-in cylinder tube (whose rendering is super fast). The only drawback with the built-in tube is that all faces seem to share the same material colors (or at least I do not know a way to change colors of a face or a cylinder within the tube).

Many thanks for your help!

Dan

You should be able to use vertexColors for this Update Vertices - Babylon.js Documentation

And you could even probably create them from parametric shapes: Parametric Shapes - Babylon.js Documentation

Yes, I am using a parametric shape: Tube. I just need ability to change the face colors of each cylinder in the Tube.

So yes, adding vertices colors would be the way to go a bit like here:
https://www.babylonjs-playground.com/#ZRZIIZ#2

Hmm…, using Tube.getVerticesData would be a starting point. However, I need to locate the individual cylinders within the Tube, because each cylinder must have a unique color assigned to it. Would be a life saver if I can pass a material color array to the Tube constructor where each color in the array will be assigned to all faces of the corresponding cylinder in the Tube.

Would also be Ok if I can address individual cylinders “conceptually” by locating the collection of faces or vertices of each “cylinder”. I guess once the Tube is constructed, we lose the concept of “cylinder” ?

If you set your wanted vertex colors, they will interpolate along each triangle from a vertex to the next one. Maybe it’s not what you want.
If you call “face” the surface along a tessellation section and if you want real different colors per face, you’ll have to have twice more vertices (2 per edge) to hold each face color. In this case, I would suggest to build your own geometry with a dedicated ribbon.

Unfortunately, we don’t have an un-capped “cylinder stacker”. :wink: I think THAT is what Dn wishes to do, easily. Me, too.

IF NOT making (inventing) a “cylinder stacker” (little tubes auto-assembled into path3d-following [bend-able] long tubes)… then yeah… each vertex of the tube… will need another vertex at same location. (as Jerome stated… it seemed) :wink:

To clarify why this must be done… it is to accomplish non-dithered color-changes. No gentle “fade-in/fade-out” color changes. Instead, DEFINITE HARD-EDGED changes. YAY US! errr. ahem.

BJS uses “color-per-vertex” system, so… ONE colorkind value for each vertex (positionkind value).

But when we have TWO verts at the same place, we have TWO colorKind values… one could be blue, and the other green. The normalkind data for each same-position vertex… would be different from one-another, though (I think) (not sure).

Let’s see, tube.convertToFlatShadedMesh()… would do what? Set 4 verts at each position? I think so. That’s overkill.

Nope, Cylinder Stacker, 1.0… CodeName: “Pippi”… Uses the new MeshStackManager class/system. :slight_smile: Custom MeshMergers. :slight_smile: Cylinders that are allowed to have one end of their cap-less “tube”… be angled. What’s that you say? Oh, BOTH ends of the cylinder should allow angle cuts? Ok, I’m cool with that, too. heh.

Then auto-parented, because meshMerging them wouldn’t work? What does a meshMerge do to colorKind data? hmm.

tube.colors = [huge,array,of,colors,applied,in,faceID,order]; (sigh). Tube internal code does all the work from there… using Jerome faery dust. :wink: (doesn’t exist, but I’m allowed to dream’n’drool, right?) :slight_smile:

Boy, am I talkin’ some crap today, eh? Really, I just wanted to make sure Dn had a hint about WHY we must double the verts of a tube… before we can get “ring-by-ring discrete colors”. Quadruple the verts… for face-by-face discrete colors? Ouch! C-yall. :slight_smile:

Wingnut,

Based on Jerome’s description, I can see why we need to duplicate vertices to get per face color.

I need each individual cylinder to have a distinct color and to be capped. I have built a series of cylinders and then used MergeMeshes with multimaterial being set to true to create a single mesh. It works, but the resulting mesh’s rendering performance is horrible compared to the equivalent tube object (100x slower!). I am not sure why it is so slow to render, I guess duplicating vertices is one of the reasons? What else could be? multi-materials?

A Cylinder Stacker enhancement to the Tube object would be a nice addition if the performance can be maintained.

On a side note: CAD and engineering applications tend not to care about vertex color: they tend to use face colors instead. Duplicating a vertex many times (up to 4 for manifold mesh or more for non-manifold) can really kill the rendering performance of a big mesh which is what I am creating.

-Dan

1 Like

Have you tried a tube.convertToFlatShadedMesh() ? Maybe look at a total mesh vert-count before and after. Depending upon what happens at the tube caps during the convert, I bet tube has 4x verts after the conversion. And, maybe look at your performance with that flat-shaded tube.

PS: I don’t even know if a tube CAN be convertToFlatShadedMesh(). I think it can. shrug. (Wear safety gear, hide pets)

If you use vertex colors, you don’t need multiple materials. Anyway, I’ve made a playground, does that look like what you have?:

https://playground.babylonjs.com/#NREUQE#1

3 Likes

Hi Gijis,

A very clever way of assigning a unique color to an entire cylinder using vertex colors. I achieved the same result using per cylinder materials instead. However, the merged meshes created with both approaches suffer the same performance lag compared to a single built-in Cylinder Tube. In my case, I have 100 tubes each with 3000 cylinders. The built-in cylinder Tubes are very fast to render, although I have no way of assigning a unique color to each cylinder in a tube.

Nonetheless, it is a very nice example.

UPDATE: I did more testing and it seems that the mesh created using vertex colors (your approach) as opposed to per cylinder material (my approach) is very fast to render as well. I’ll do more testing to confirm this.

Thanks,
Dan

1 Like

the cylinder stacker already exists for the Cylinder object. Just use the optional parameter hasRings.
Is this what @Dn_Jiang wants ? or is this different colors along the tessellated vertical faces ?
a PG would be nice to see what is the wanted goal

Oh, thx. Yeah, that’s not too bad… https://www.babylonjs-playground.com/#19ERV9#1 Impossible to bend in a flexible tube-like manner, though. In Gijs’s “kinky” playground, look at the 3rd cylinder (camera end). It has 2 bends in it (how did he do that?). :slight_smile: Others have a single bend, and we never know if bend is located in center of “tube run”, or nearer to one end or the other. And, all his cyls are the same height, and that’s also a limitation of has-rings-like ops.

Let’s pretend each of Gijs’s cylinder are the same radius/diameter… and that we try to move a sphere of appropriate diameter… down thru his tube-o-cylinders. At every bend-point, the sphere would protrude thru the sides of the cylinder, because the diameter of the tube SHRINKS at every bend-point, right?

A stack manager would be more powerful. Let’s pretend we wish to turn the hasRings cylinder-tube… 90 degrees, toward +x (in the middle of the tube-run). To do that turn, as tight as possible, and as gradual as possible, (don’t allow the tubing to change diameter during the turn)… then one could imagine that it would take 88 (super-low-height) cylinders to make a smooth 90-degree turn that maintained diameter as best it could. 180 degree turns (hair-pins) would require 178 cylinders… each performing 1 degree of angle change. This is probably the BEST chance to get a sphere to travel the tube… without protruding thru tube walls at corners.

This tube-assembling manager would essentially need a scripting language of its own.

tube.turn(startingAtTubeRunPercentage (50% = middle), newDirection (+x), steps (88));

A command like that… would generate the 88 (89?) slanted-top cylinders needed to make a no-diameter-change 90-degree turn… either automatically parenting them into perfect positions, or… some other way (tube builder code).

Me, working in the petroleum industry (not)… we need to get those pipe-inspection-gauges (pigs) to go around pipe-corners properly, without binding the pig. That means, no diameter changes allowed on pipe turns. :wink:

I can’t get THIS playground to run anymore, but it has a real nice tube bend… the best I have ever seen, and that’s why I bookmarked it. It is a tube “brancher”, too, rare/difficult.

Probably coded by you, Jerome. :slight_smile: When working, it does two 45-degree turns in a very small space, and appears to NOT screw-up (shrink) its tube diameter during the turn. I drooled. :slight_smile: Certainly better than my early attempts at consistent tube diameter during turns.

I think I talked about all this before… how path-points need to be close-together on turns… but can be far-apart on straight-runs. BUT, if you have a camera or “car” following a path3d… that has path-points with variable spacing (many around corners, less on straight runs)… the car/cam moves much faster on straight runs… than around tight corners.

This is the reason why ONE of the cylinders in Gijs’s PG… has TWO bends in it. It needed to make a “tight” corner during its “run”… and therefore added more subdivs/bend-points (more rings).

This is all difficult to explain… and I confuse myself while I talk about it. Since the manager is able to “look ahead” (it knows the user wants to do a 90-degree turn to the right in 1-degree ring-turn increments), then it knows it will need to add 88/89 slant-top cylinders DURING the turn… and that would be automated by the manager. Maybe not possible, and maybe low use-case… not sure. Also, I’m off-topic a bit, sorry.

A picture is worth a thousand words. An image showing your creation would help me to understand what you want to achieve.

I have got it working. Here is the Drill Hole Visualizer of our 3D Geobase in Babylonjs (click Create 3D Version button to view the 3D drill holes, each consisting of potentially hundreds of cylinders):
https://3dgeobase.com/Visualization

Maybe this could be a good showcase for Babylonjs!?

Ok, I understand better what you’re trying to achieve.
If I were you and as the data are available, so known, before the geometry is to be build and they don’t change then, I would use a SPS from a single cylindrical model with as many solid particles as the required number of colored cylinders in your scene.

This topic does something similar with SPS and cylinders Combining meshes without drawing them and performance issues. It is certainly worth reading and checking out the PGs.

1 Like