First of all, hopefully the devs will let us add this in soon 😉
👉 https://projects.blender.org/blender/blender/pulls/104621 .
Anyway, until then there are several ways you can do this, or at least two methods that I know of:
- Sample nearest
- Accumulate field
- Geometry proximity (4.2+)
Preface
First let's think about what we want. We have two IDs (or keys); the one you are sampling from and the one you are transferring to. Based on these IDs matching we want to transfer an attribute from the A to B (the sampled to the sampler).
What problem could we face? I could think of two that we would need to account for:
- What if there doesn't exist a match for an ID in the sampler from sampled geometry?
- What if there are multiple matches for an ID in the sampler from sampled geometry?
In regards to sampling the attribute it's best to go with the index, meaning our match ID operation will produce the index of the point you want to sample.
Now to address the potential problems I mentioned above: first, we'll output a boolean value as to whether or not there is a match (true = there is a match).
Second, we could either use the first match, or (what I will do) you can have an option to specify on the sample geometry which match to sample from (first, second, third, etc...).
And just as a bonus I like to add the total number of matches.
Here is a setup for the first way - sample nearest:
and this is how the node looks:
The idea here is to use the position as the ID (or the ID as the position) and take advantage of the source position (otherwise you could just set the position of both).
- We set the position of the target geometry (the sampled geo) to its ID
- Then we sample the nearest position while setting the sampler geometry's position also to be its ID.
So now the nearest point should be the one with the same ID.
To solve the issue of no matches we sample the ID at that index to see if it is a true match.
And for duplicate matches we offset any duplicates in the y direction by its "local index" within its ID - using the accumulate field - and add out sort index [which is an offset to pick which match to use] to the samplers y position.
Lastly I sample the total from the accumulate field, which gives me how many duplicates there are.
One last issue is that the sort index isn't constrained by the total duplicates. For this you could sample a second time and modulo it by the total. (not recommended, because this is just too many sample nearest's for my liking)
btw that looks like this:
Here is a setup for the second way - accumulate field:
and this is how the node looks:
The trick with this one is to combine both geometries and use the IDs as a group (for accumulate field). We take the total Index of the group excluding the sampler, which leaves us with the index of the point on the target geo that matches the one on the sampler.
From this point you could either capture the index and delete the extra (target) geo, or sample the result back to the original geo.
I went with the latter one, but both are fine.
some points to think about:
- If you are gonna sample the result back to the original geo (like I did) then you need to make sure that the sampler geometry is the top input of the join geometry.
- To deal with duplicate matches I added more group IDs, one for each duplicate. I did this by multiplying the "local index" per ID with the max ID and then adding that to the IDs [keys]; What this does is append these new IDs the the end of the other IDs. Then I do the same thing to the sort index except I wrap them by the total duplicate amount.
- What if there doesn't exist a match? Since I take the total already, if there is no match then the total matches are 0, so I just compare that.
- with the total, since I take it before I specify a sort index, so I just take it from the first point. The rest of the points are shoved into another group and ignored for this calculation - this is where I have the switch with the top integer being an arbitrary improbable (negative) number.
I have more, but that is for another day 😉.
Geometry proximity method
Now in 4.2+ they added a group ID to the geometry proximity node so we could use that so basically circumvent the proximity part, and just use it to to get the data from the matching element.
This doesn't have some of the sort index thing like we implemented for the sample nearest, but it's mysh faster so I would take this over the other one.
One thing I use it for a lot is to transfer a boolean, which is the easiest. Just make the group ID to -1 or something and use the index and the sample ID and use the is valid output. I used this all the time, and it's very straight forward easy and fast. I even hide the extra inputs and it look really clean and like a new node 😄.
here i used it for Instance on points based on probability:
If you want to send data across then you would set position of the geometry (input) to the data you want and set the sample position to 0, and the output position will be the data you set.
here is a sort index, but on the sources side:
You could also average the value per ID that goes into the set position. or pass the index through and use with sample index, if you needed to sample a lot of values etc. I'll leave the rest up to you.
If they add this ID option to the sample nearest node then that will basically be the same as the proposed "sample by ID" node; and I'm not sure how to feel about that. I'm still a fan of the index map node; hope we get it back to consideration 🤷♂️.
PS: A native node like this has been in blender development for some time.
There are two projects and they just got merged
There is the original by iliya which is called the 'index map' node
and there us one called Sample by Group ID by Simon Thommes.
I this the 'Index Map' design is much better and we should go with that.
I suggest, if you desire this node in blender, to join the discussion or leave and emoji or something letting the developers know you want it. It has been too long and we need the community's interest to get this node into blender sooner.