polarTransform per-point rotation

This is a response to a question in this thread, trying to keep one question per thread.

I’ve added this example scene, which may help: https://polygonjs.com/demo?example=bynode/sop/data/advancedwithcopy

And one thing that’s probably not clear in Polygonjs yet is which parameter can take an expression that varries per point, and which cannot. So I still have to make examples/docs explaining that.

But in short, the sop/point, sop/attribCreate are not that can take per-point expressions (where you can use @P to refer to the position of that point, or @ptnum to its index), but the sop/transform or sop/polarTransform cannot.

And that choice of which node can or cannot is mostly done for performance reasons.

(If the polarTransform was able to use per-point expressions, then you could replace the index 0 by @ptnum, but that will not have any effect at the moment.)

So then the question is how to we get around that. And that’s where a node like the sop/copy can really help. It’s not just useful to duplicate objects, but also to iterate over a list. That’s mainly what the example above shows.

Basically, the points created by the sop/data node are not the ones that end up being displayed. They are just used as reference by other nodes.

In the left branch, the data node is read. And in the right branch, those are the displayed point, and the point and polarTransform nodes have expression that use the copy expression, which returns the index of the current copy created. This is what allows the point and polarTransform to apply a different operation per point.

completely forgot to CC you, @MDH :grimacing: (above is my answer to your previous question about the polarTransform )

WOW!!! Thank you very much Gui! :raised_hands:

This is very interesting. If I understand it correctly, in this case it is not possible to use the instance node instead of the copy node, right?
I only ask, because the instance node might be more powerful if the point number is very large.

Merging the points via the “merge node” is supposed to compensate for this, after all. However, you might lose the possibility to interact with the individual points later (e.g. color change on mouse click). And you will probably lose the connection between the visual data point and the data entry in the database which would be necessary if I would like to show the corresponding database entry by clicking on a single point. :thinking:

But nonetheless, this is a great example you’ve created. And it will certainly help to understand the logic of polygonjs. So thanks again :slightly_smiling_face:

Glad that helps!

And you could still use the instance node. Although it wouldn’t use the output of the data node, but instead the output of the merge node in the example above.

In both case, whether you use the instance node or not, it’s still possible to detect what is under the mouse (when clicking or on hover). You’d use either this technique for instances, or that one for copy.

Similarly, you can preserve the data from the database on the whole chain. Just like we propagate P and RotateY, you could propagate any other attribute, such as an id or any other.

Oh ok. I am not sure if I understood you correctly on this. The merge node comes after the copy node which I want to replace with an instance node. So I need to delete the copy node and place an instance node after the merge node?
However - for the moment “copy” is enough for me as a solution I guess.

You’d use either this technique for instances, or that one for copy.

Ok. Sounds good. However - at the moment, I am using a “points” material which seems be a bit different compared to the “meshStandard” material. But it’s good to know that it is possible. Sooner or later I will find a solution. :smiley: :+1:

EDIT: → the “copy” version of the material-change-solution works pretty well now. Even with a point material. :heart_eyes:

Thanks for all the helpful hints. And please excuse me for asking so many stupid questions. I’m someone who knows a bit about 3D graphics, but I’m also someone who is quickly at a loss if I don’t have a traditional user interface to create 3D graphics. :grimacing:

1 Like

Oh don’t worry at all, there are definitely no stupid questions in my book. Especially in the context of a new app while you’re learning it.

And sources of confusion or bugs like the sop/fileJSON vs sop/dataUrl are totally on me. That’s the type of problem that you should ideally not have to face.

So please absolutely don’t hesitate asking me questions whenever you need. This battle-tests polygonjs and only makes it better. And I’m thankful for that.

Now, regarding the instance node after the merge node, maybe this scene can help clarify. The instance node does not replace the copy, but indeed comes after (at least if I understood correctly what you are trying to achieve). So the role of the copy in this scene is really to position the points how you want. Then, assuming you want to use those points to position other objects, the instance node does that part.

And I’ve also added a 2nd copy node, next to the instance. So they are sort of interchangeable in this case.

You can also see both have a material where the id attribute drives the color. So that shows how to have that id flow from the data nodes up until the end of the chain.

As for meshStandard vs point material, they offer similar customisations. For each material, you can find a “builder” equivalent. So you’ll have meshStandardBuilder and pointBuilder. And inside those you can create other nodes, which will help customize them. So the nodes in the example I linked can be created similarly inside a pointsBuilder.

Here is for instance how the material applied to the instance node is setup. The attribute node reads the ‘id’ attribute, and that goes to the color (and in between id is converted to a random value, then to vector3, then to hsv and then to rgb). Try and change any of those nodes to see how it affects the color.

Hope it all makes sense, but don’t hesitate if that’s not the case. There may very well be something crucial I haven’t explained correctly yet, so am very happy to help on that.

1 Like

Oh wow. :open_mouth:

The instance node does not replace the copy, but indeed comes after […]

Hm. In fact, I didn’t really want to put 3D objects at the positions of the points. The points themselves are already perfect. I just thought that if you want to display a few million vertex points in the viewport, it would certainly be better to use an instance node instead of a copy node. So I thought I should try to do without the copy node.

You can also see both have a material where the id attribute drives the color. So that shows how to have that id flow from the data nodes up until the end of the chain.

This is pretty cool, indeed!

For each material, you can find a “builder” equivalent. […] And inside those you can create other nodes, which will help customize them.

WOW. This is probably the most important learning for me today. Being able to extend the standard material parameters is very powerful! And that’s how you get all the complex behaviors built in. That will certainly keep me busy for a while now. :smiley:

1 Like

Cool, glad that helps.
And thank you for clarifying your end goal. As you mention millions of points, that may indeed complete the task at hand! :smiley:
I think the way to go would be to do as much transformations in the shader. Otherwise, moving millions of points using the polarTransform or the copy will be challenging for most browsers. So I’d recommend you to investigate in that direction.

After that you could also look at the particle systems. Those are designed with the same nodes as the material (that’s because they both run on the GPU), and that may allow you to move points around dynamically. Or maybe that’s overkill, not sure now, but I thought I’d mention them to give you an overview of the tools available.

What I’m not sure though, is how to fetch millions of items from a bubble database and use that (again, I’m making another assumption, which is that each point matches one database entry - that could be wrong). It might be that you’d need custom code, to write the bubble data to a texture, which could then be efficiently read in the shader that positions the points.

Anyway, that’s food for thought, I’ll let you investigate further. Curious to see how that pans out!

1 Like