Function Node: Hash Value #110769

Merged
Jacques Lucke merged 28 commits from CharlieJolly/blender:gn-hash-node into main 2024-08-30 16:42:48 +02:00
Member

This node hashes float, vector, color, string and integers to a hash.

Uses hash functions from BLI_noise.hh.

These are also used in White Noise node.

I'm not experienced enough with the hash functions to know if
the int/uint conversion is a real issue or not.

Originally suggested in comments for D15375

Based on archived patch: https://archive.blender.org/developer/D15835

Mentioned here: #103457

image

This node hashes float, vector, color, string and integers to a hash. Uses hash functions from BLI_noise.hh. These are also used in White Noise node. I'm not experienced enough with the hash functions to know if the int/uint conversion is a real issue or not. Originally suggested in comments for D15375 Based on archived patch: https://archive.blender.org/developer/D15835 Mentioned here: https://projects.blender.org/blender/blender/issues/103457 ![image](/attachments/79fd45ab-8915-472f-953e-5b0a6d3a6673)
Charlie Jolly added 2 commits 2023-08-03 17:02:39 +02:00
This node hashes float, vector, color, string and integers to a hash.

Uses hash functions from BLI_hash and BLI_noise.

Suggested in comments for D15375

Based on https://archive.blender.org/developer/D15835
Charlie Jolly added this to the Nodes & Physics project 2023-08-03 17:02:50 +02:00
Iliya Katushenock added the
Interest
Geometry Nodes
label 2023-08-03 17:04:39 +02:00
Jacques Lucke requested changes 2023-08-03 17:37:38 +02:00
Jacques Lucke left a comment
Member

We haven't discussed that in a meeting yet, but currently I think this is a useful low level building block.

We haven't discussed that in a meeting yet, but currently I think this is a useful low level building block.
@ -0,0 +88,4 @@
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
static auto fn_hash_float = mf::build::SI1_SO<float, int>(
"Hash Float", [](float a) { return get_default_hash(a); }, exec_preset);
Member

This hash is not designed to generated very random results in these cases, it shouldn't be exposed in the node.
Just expose the noise::hash functions like you did below. Those are used indirectly by noise code already anyway.

This hash is not designed to generated very random results in these cases, it shouldn't be exposed in the node. Just expose the `noise::hash` functions like you did below. Those are used indirectly by noise code already anyway.
Author
Member

I'll wait for meeting discussion but I guess the suggestion is to remove all the get_default_hash methods and just use the BLI_noise functions? This also simplifies node without the need for users to choose the method. This was originally added to explore what was useful or not.

I'll wait for meeting discussion but I guess the suggestion is to remove all the `get_default_hash` methods and just use the BLI_noise functions? This also simplifies node without the need for users to choose the method. This was originally added to explore what was useful or not.
Member

I guess the suggestion is to remove all the get_default_hash methods and just use the BLI_noise functions?

Yeah, that's what I meant.

> I guess the suggestion is to remove all the get_default_hash methods and just use the BLI_noise functions? Yeah, that's what I meant.
CharlieJolly marked this conversation as resolved
Charlie Jolly added 1 commit 2023-08-03 18:17:43 +02:00

I agree with Jacques, the node seems very useful, I often think about it when I work with groups.

  1. Replace NodeHashMode by simply socket types.
  2. Iterate over all sockets in node_update and compare types.
  3. Wrap all static auto fn_hash_vector in bke::attribute_math::convert_to_static_type (use socket_type_to_custom_data_type) (wrap in constexpr if statement to not generate code for unsupported types (See accumulate or blur attribute nodes as example)).
  4. Use simple for-loop in node_gather_link_searches (nodeStaticSocketLabel, std::string = "HashFor" + nodes::...(type) can be captured by lambda [name = std::move(name)]). And make sure, if connected sockets types is converteble (bke function).
  5. Store all node data in custom1.
  6. Rotation socket can be added too.
I agree with Jacques, the node seems very useful, I often think about it when I work with groups. 1. Replace `NodeHashMode` by simply socket types. 2. Iterate over all sockets in `node_update` and compare types. 3. Wrap all `static auto fn_hash_vector` in `bke::attribute_math::convert_to_static_type` (use `socket_type_to_custom_data_type`) (wrap in constexpr if statement to not generate code for unsupported types (See accumulate or blur attribute nodes as example)). 4. Use simple for-loop in `node_gather_link_searches` (`nodeStaticSocketLabel`, `std::string = "HashFor" + nodes::...(type)` can be captured by lambda `[name = std::move(name)]`). And make sure, if connected sockets types is converteble (bke function). 5. Store all node data in `custom1`. 6. Rotation socket can be added too.

This node seems generic enough to be found in utilities like Random Value node.

This node seems generic enough to be found in utilities like Random Value node.
First-time contributor

btw how does this work? what does a string turn into? and can you convert a hash into a string? that would be pretty cool.
and what would a float look like after it's converted back and forth?

btw how does this work? what does a string turn into? and can you convert a hash into a string? that would be pretty cool. and what would a float look like after it's converted back and forth?

Hash, this is the thing that may not be stabile very much from many things. You don't even have to think about converting data to and from hash.

Hash, this is the thing that may not be stabile very much from many things. You don't even have to think about converting data to and from hash.
First-time contributor

@mod_moder you are saying it isn't stable and you can't convert things back and forth. in that case, why and how to you have these conversion to a hash and from a hash. I'm unsure on the behavior.

@mod_moder you are saying it isn't stable and you can't convert things back and forth. in that case, why and how to you have these conversion to a hash and from a hash. I'm unsure on the behavior.

@shmuel You can get a random number for any data. It must be identical for the same data. But even just x = 10 * 4 / x = 10 + 10 + 10 + 10 for float will actually give us different real numbers and its hashs.

@shmuel You can get a random number for any data. It must be identical for the same data. But even just `x = 10 * 4` / `x = 10 + 10 + 10 + 10` for float will actually give us different real numbers and its hashs.
Charlie Jolly added 2 commits 2023-08-04 20:30:26 +02:00
Remove node storage and use custom1
Use SocketSearchOp
Address some comments from @mod_moder
Iliya Katushenock reviewed 2023-08-04 20:42:08 +02:00
@ -0,0 +128,4 @@
}
if (params.in_out() == SOCK_IN) {
if (type == CD_PROP_FLOAT) {
params.add_item(IFACE_("Value"), SocketSearchOp{"Value", type});

To clarify a little: we must add all options if their type can be converted to type. So, for string is {sring}, for color, is {all, except of string and rotation}, ... . That's the point of the loop and the function to check if the socket types are convertible.

To clarify a little: we must add all options if their type can be converted to `type`. So, for string is {sring}, for color, is {all, except of string and rotation}, ... . That's the point of the loop and the function to check if the socket types are convertible.
Author
Member

For inputs I'm not sure this is needed. I'd expect to hash by type so only having the one option reduces clutter. So plugging in a Float will use the Float To Hash function etc.

I have added Boolean socket and mapped that to Int.

For inputs I'm not sure this is needed. I'd expect to hash by type so only having the one option reduces clutter. So plugging in a Float will use the Float To Hash function etc. I have added Boolean socket and mapped that to Int.

Node to convert Float to Int doesn't make sense if you create this via drag-and-drop from int output socket of other one node so it is connected to float input, but this still exist in the list to search/

Node to convert Float to Int doesn't make sense if you create this via drag-and-drop from int output socket of other one node so it is connected to float input, but this still exist in the list to search/
Author
Member

Maybe you can add a screen shot because I'm not sure I understand.

Maybe you can add a screen shot because I'm not sure I understand.

This search result makes no sense. But it still exists:

Drag and Drop search Result

Your node should also show all options, and not just those that are equal to current socket type.

This search result makes no sense. But it still exists: | Drag and Drop search | Result | | -- | -- | | ![](https://cdn.discordapp.com/attachments/340195875399663617/1159060583732215899/image.png) | ![](https://cdn.discordapp.com/attachments/340195875399663617/1159060583421841448/image.png) Your node should also show all options, and not just those that are equal to current socket type.
Author
Member

Sorry, I still don't understand. Drag link only limits by type not node. Hash output is Integer. User might want to plug that into a math node.

Sorry, I still don't understand. Drag link only limits by type not node. Hash output is Integer. User might want to plug that into a math node.

I mean, node_gather_link_searches have to create search items all input socket for all the types supported by the node, and the output one kind at the single call (noy only one input and one output for supported type). Only one limitation of what socket can not be converted to other type by implicit value conversion.

I mean, `node_gather_link_searches` have to create search items all input socket for all the types supported by the node, and the output one kind at the single call (noy only one input and one output for supported type). Only one limitation of what socket can not be converted to other type by implicit value conversion.
Author
Member

It might be easier for you to provide code if you need me to change something here.

Or are you talking about weight as is done for math node?

It might be easier for you to provide code if you need me to change something here. Or are you talking about weight as is done for math node?
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
  static const std::array<eNodeSocketDatatype> supported_types{...};
  const eNodeSocketDatatype other_type = eNodeSocketDatatype(params.other_socket().type);

  if (ELEM(other_type, SOCK_STRING)) {
    return;
  }

  for (const eNodeSocketDatatype item_type : supported_types) {
    if (params.in_out() == SOCK_OUT) {
      if (!ELEM(SOCK_ROTATION, other_type, item_type)) {
        params.add_item(IFACE_("Hash"), SocketSearchOp{"Hash", CD_PROP_INT32});
      }
      continue;
    }
    if (!ELEM(SOCK_ROTATION, other_type, item_type) || item_type == other_type) {
      params.add_item(IFACE_("Value"), SocketSearchOp{"Value", type});
    }
  }
}
```Cpp static void node_gather_link_searches(GatherLinkSearchOpParams &params) { static const std::array<eNodeSocketDatatype> supported_types{...}; const eNodeSocketDatatype other_type = eNodeSocketDatatype(params.other_socket().type); if (ELEM(other_type, SOCK_STRING)) { return; } for (const eNodeSocketDatatype item_type : supported_types) { if (params.in_out() == SOCK_OUT) { if (!ELEM(SOCK_ROTATION, other_type, item_type)) { params.add_item(IFACE_("Hash"), SocketSearchOp{"Hash", CD_PROP_INT32}); } continue; } if (!ELEM(SOCK_ROTATION, other_type, item_type) || item_type == other_type) { params.add_item(IFACE_("Value"), SocketSearchOp{"Value", type}); } } } ```
Author
Member

I'm still not understanding what this is doing different other than using an array and excluding Rotation socks.

I'm still not understanding what this is doing different other than using an array and excluding Rotation socks.
With all possible node types Current one
| With all possible node types | Current one | | -- | -- | | ![](https://cdn.discordapp.com/attachments/340195875399663617/1159193380962697276/image.png) | ![](https://cdn.discordapp.com/attachments/340195875399663617/1159193381361176617/image.png) |
Author
Member

Ok, I get what you are saying but we're not consistent here. E.g. Map Range doesn't list all available sockets. Listing all sockets also adds noise that the user needs to go through. In most cases, users will be hashing the data type associated with the socket so current behaviour seems favourable to me.

Ok, I get what you are saying but we're not consistent here. E.g. Map Range doesn't list all available sockets. Listing all sockets also adds noise that the user needs to go through. In most cases, users will be hashing the data type associated with the socket so current behaviour seems favourable to me.

That was my mistake.

That was my mistake.
mod_moder marked this conversation as resolved
Charlie Jolly added 1 commit 2023-08-07 17:25:21 +02:00
Charlie Jolly added 1 commit 2023-08-07 17:31:10 +02:00
Charlie Jolly added 2 commits 2023-10-03 14:16:43 +02:00
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/makesrna/intern/rna_nodetree.cc
#	source/blender/nodes/function/node_function_register.cc
#	source/blender/nodes/function/node_function_register.hh
Charlie Jolly added 1 commit 2023-10-03 14:19:51 +02:00
Charlie Jolly added 1 commit 2023-10-04 11:28:12 +02:00
Charlie Jolly added 1 commit 2023-10-04 11:57:45 +02:00
Member

The code generally looks good. I think the main thing that's missing in the description is the motivation and examples for how someone should use this. Like, why should this be used instead of White Noise for example?

The code generally looks good. I think the main thing that's missing in the description is the motivation and examples for how someone should use this. Like, why should this be used instead of White Noise for example?
Author
Member

The code generally looks good. I think the main thing that's missing in the description is the motivation and examples for how someone should use this. Like, why should this be used instead of White Noise for example?

This was originally motivated as a response to the comments in D15375. 😝

image

https://archive.blender.org/developer/D15375

White Noise only handles float data so this compliments that to allow users to hash data for indexes etc

@mod_moder Has also mentioned it here Attribute Map node #103457

> The code generally looks good. I think the main thing that's missing in the description is the motivation and examples for how someone should use this. Like, why should this be used instead of White Noise for example? This was originally motivated as a response to the comments in D15375. 😝 ![image](/attachments/07b2cb40-6613-4148-bd68-3dedb7f1785f) https://archive.blender.org/developer/D15375 White Noise only handles float data so this compliments that to allow users to hash data for indexes etc @mod_moder Has also mentioned it here Attribute Map node #103457

Hash is a good thing to have during groups building from non-integer noises.
Multidimensional hash can be used in recreating all noise textures as node groups (as the base noise node).

Hash is a good thing to have during groups building from non-integer noises. Multidimensional hash can be used in recreating all noise textures as node groups (as the base noise node).
Jacques Lucke requested review from Simon Thommes 2023-10-09 11:48:12 +02:00
Jacques Lucke requested review from Hans Goudey 2023-10-09 11:48:12 +02:00
Simon Thommes requested changes 2023-10-09 14:57:55 +02:00
Dismissed
Simon Thommes left a comment
Member

To me it's not immediately obvious, why there are 3 inputs for the Integer type. I can see needing 2, but that should be enough to hash any amount of integers together by folding.
Also this seems a bit strange in comparison with the other types. I'd propose the following:
Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type.

The main input to be hashed should be called Value regardless of the type for consistency with other nodes, e.g. store named attribute.

I'm not sure about the name of the node and the output. I think it's fine to introduce the term hash, as it's descriptive, but we don't have that anywhere in the UI yet afaik. It might be worth considering the term ID instead in something like ID from Value, Random ID, ... to avoid introducing new terms.

@dfelinto , what do you think?

To me it's not immediately obvious, why there are 3 inputs for the Integer type. I can see needing 2, but that should be enough to hash any amount of integers together by folding. Also this seems a bit strange in comparison with the other types. I'd propose the following: Add a `Seed` integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type. The main input to be hashed should be called `Value` regardless of the type for consistency with other nodes, e.g. store named attribute. I'm not sure about the name of the node and the output. I think it's fine to introduce the term hash, as it's descriptive, but we don't have that anywhere in the UI yet afaik. It might be worth considering the term `ID` instead in something like `ID from Value`, `Random ID`, ... to avoid introducing new terms. @dfelinto , what do you think?
Member

Design-wise, combining hash-to-float in a node that otherwise just creates integers is a bit confusing. Maybe that should be a separate node? It also seems a bit arbitrary for the integer mode to have three inputs where the float mode only has one. I guess in an ideal world the number of inputs would be dynamic. Other than that, I do think this node makes sense!

Design-wise, combining hash-to-float in a node that otherwise just creates integers is a bit confusing. Maybe that should be a separate node? It also seems a bit arbitrary for the integer mode to have three inputs where the float mode only has one. I guess in an ideal world the number of inputs would be dynamic. Other than that, I do think this node makes sense!
Member

combining hash-to-float

Where is that happening? Did I miss something? Afaict the node is always just creating integer hashes.

> combining hash-to-float Where is that happening? Did I miss something? Afaict the node is always just creating integer hashes.
Member

Where is that happening? Did I miss something? Afaict the node is always just creating integer hashes.

I just saw it in the screenshot in the description.

>Where is that happening? Did I miss something? Afaict the node is always just creating integer hashes. I just saw it in the screenshot in the description.
Author
Member

hash-to-float was removed, some changes were discussed in Blender chat a while ago but the node didn't have any tlc for a bit!

`hash-to-float` was removed, some changes were discussed in Blender chat a while ago but the node didn't have any tlc for a bit!
Author
Member

To me it's not immediately obvious, why there are 3 inputs for the Integer type. I can see needing 2, but that should be enough to hash any amount of integers together by folding.

The hash functions take 1, 2, 3 or 4 inputs. Exposing 3 seemed a good compromise here for hashing integer based positions.

Also this seems a bit strange in comparison with the other types. I'd propose the following:
Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type.

This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value.

The main input to be hashed should be called Value regardless of the type for consistency with other nodes, e.g. store named attribute.

We're not consistent here, see Map Range which has Value and Vector inputs depending on type.

I'm not sure about the name of the node and the output. I think it's fine to introduce the term hash, as it's descriptive, but we don't have that anywhere in the UI yet afaik. It might be worth considering the term ID instead in something like ID from Value, Random ID, ... to avoid introducing new terms.

@dfelinto , what do you think?

I'm not opinionated on this.

> To me it's not immediately obvious, why there are 3 inputs for the Integer type. I can see needing 2, but that should be enough to hash any amount of integers together by folding. The hash functions take 1, 2, 3 or 4 inputs. Exposing 3 seemed a good compromise here for hashing integer based positions. > Also this seems a bit strange in comparison with the other types. I'd propose the following: > Add a `Seed` integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type. This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value. > > The main input to be hashed should be called `Value` regardless of the type for consistency with other nodes, e.g. store named attribute. We're not consistent here, see Map Range which has `Value` and `Vector` inputs depending on type. > > I'm not sure about the name of the node and the output. I think it's fine to introduce the term hash, as it's descriptive, but we don't have that anywhere in the UI yet afaik. It might be worth considering the term `ID` instead in something like `ID from Value`, `Random ID`, ... to avoid introducing new terms. > > @dfelinto , what do you think? I'm not opinionated on this.
Member

We're not consistent here, see Map Range which has Value and Vector inputs depending on type.

Let's just use the word "Value," it's simpler and using other words is redundant with the socket type itself.

The hash functions take 1, 2, 3 or 4 inputs. Exposing 3 seemed a good compromise here for hashing integer based positions.

Since there's a performance cost for hashing more values, I'd probably go with 2 for now until the amount of inputs could be dynamic. But it's not a big deal either way.

>We're not consistent here, see Map Range which has Value and Vector inputs depending on type. Let's just use the word "Value," it's simpler and using other words is redundant with the socket type itself. >The hash functions take 1, 2, 3 or 4 inputs. Exposing 3 seemed a good compromise here for hashing integer based positions. Since there's a performance cost for hashing more values, I'd probably go with 2 for now until the amount of inputs could be dynamic. But it's not a big deal either way.
Member

Also this seems a bit strange in comparison with the other types. I'd propose the following:
Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type.

This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value.

To me it's a matter of the consistency of the design and usability. You could argue for the integer input type just as well, that you could just have a single input and offset it, if you need a different hash. I think it's reasonable to avoid such workarounds to allow multiple inputs hashed together. And rather than having those different for every type I think it's more intuitive, more consistent with other existing nodes and nicer design to introduce that second input as a seed integer value. how much does it complicate the code? To me it is still worth it, if it's not by that much. I'm quite confident that this is a nice solution on the user level.
Maybe someone more technical can evaluate this better on the code level @HooglyBoogly ?

> >Also this seems a bit strange in comparison with the other types. I'd propose the following: > > Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type. > > This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value. To me it's a matter of the consistency of the design and usability. You could argue for the integer input type just as well, that you could just have a single input and offset it, if you need a different hash. I think it's reasonable to avoid such workarounds to allow multiple inputs hashed together. And rather than having those different for every type I think it's more intuitive, more consistent with other existing nodes and nicer design to introduce that second input as a seed integer value. how much does it complicate the code? To me it is still worth it, if it's not by that much. I'm quite confident that this is a nice solution on the user level. Maybe someone more technical can evaluate this better on the code level @HooglyBoogly ?

Concentrating the comments, the node declaration should be?:

  • Value input (any type).
  • Seed input (int).
  • Hash output.
Concentrating the comments, the node declaration should be?: - Value input (any type). - Seed input (int). - Hash output.
Author
Member

Also this seems a bit strange in comparison with the other types. I'd propose the following:
Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type.

This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value.

To me it's a matter of the consistency of the design and usability. You could argue for the integer input type just as well, that you could just have a single input and offset it, if you need a different hash. I think it's reasonable to avoid such workarounds to allow multiple inputs hashed together. And rather than having those different for every type I think it's more intuitive, more consistent with other existing nodes and nicer design to introduce that second input as a seed integer value. how much does it complicate the code? To me it is still worth it, if it's not by that much. I'm quite confident that this is a nice solution on the user level.
Maybe someone more technical can evaluate this better on the code level @HooglyBoogly ?

@HooglyBoogly @JacquesLucke how do you want me to implement the seed here? The current node is simply wrapping the noise::hash functions at present.

E.g.

For Float3, I can call hash_float(float4(a.x, a.y, a.z, float(seed))) or hash_float(float3(a.x, a.y, a.z) + float(seed))

For Rotation, I could call hash_float(float4(a.x, a.y, a.z, a.w) + float(seed))

For String, do we introduce a new function?

> > >Also this seems a bit strange in comparison with the other types. I'd propose the following: > > > Add a Seed integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type. > > > > This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value. > > To me it's a matter of the consistency of the design and usability. You could argue for the integer input type just as well, that you could just have a single input and offset it, if you need a different hash. I think it's reasonable to avoid such workarounds to allow multiple inputs hashed together. And rather than having those different for every type I think it's more intuitive, more consistent with other existing nodes and nicer design to introduce that second input as a seed integer value. how much does it complicate the code? To me it is still worth it, if it's not by that much. I'm quite confident that this is a nice solution on the user level. > Maybe someone more technical can evaluate this better on the code level @HooglyBoogly ? @HooglyBoogly @JacquesLucke how do you want me to implement the seed here? The current node is simply wrapping the `noise::hash` functions at present. E.g. For Float3, I can call `hash_float(float4(a.x, a.y, a.z, float(seed)))` or `hash_float(float3(a.x, a.y, a.z) + float(seed))` For Rotation, I could call `hash_float(float4(a.x, a.y, a.z, a.w) + float(seed))` For String, do we introduce a new function?

@CharlieJolly blender::get_default_hash_2<T, int> (from bli)

@CharlieJolly `blender::get_default_hash_2<T, int>` (from `bli`)
Author
Member

@CharlieJolly blender::get_default_hash_2<T, int> (from bli)

From previous review from Jacques it was decided to expose noise::hash functions and not default_hash.

> @CharlieJolly `blender::get_default_hash_2<T, int>` (from `bli`) From previous review from Jacques it was decided to expose `noise::hash` functions and not `default_hash`.
Charlie Jolly added 2 commits 2023-10-11 17:19:42 +02:00
Charlie Jolly added 1 commit 2023-10-11 22:52:10 +02:00
Use a single Integer input
Use eNodeSocketDatatype not eCustomDataType
Use dynamic declaration and remove updatefunc
Charlie Jolly added 1 commit 2023-10-11 22:54:25 +02:00
Author
Member

With Seed socket and one input for each hashable type

image

With Seed socket and one input for each hashable type ![image](/attachments/2843c7f3-015d-4918-977e-e71ee0b42a95)
Member

That looks great to me now, thank you!

I still haven't actually tested functionality but as that is pretty straightforward, I'll trust the code review on that.

I'm still not 100% sure about exposing the 'new' term Hash in the UI, as we don't use that anywhere else. I just briefly talked to Andy as well and now I do think that since.
The term hash can totally be in the docs and output socket description imo. But since no other socket has that name, it seems like we're introducing a new concept, that doesn't really add that much being called its own term. So I would propose reusing the ID term here.

The only issue is that while hash works nicely as a Verb, ID does not. Personally I'd lean most towards ID from Value, but maybe there's a better name.
Since I might also be misinterpreting the similarity of the terms I'd still like this to be signed off by the dev team.
I'll put it on the agenda of the next meeting.

That looks great to me now, thank you! I still haven't actually tested functionality but as that is pretty straightforward, I'll trust the code review on that. I'm still not 100% sure about exposing the 'new' term `Hash` in the UI, as we don't use that anywhere else. I just briefly talked to Andy as well and now I do think that since. The term hash can totally be in the docs and output socket description imo. But since no other socket has that name, it seems like we're introducing a new concept, that doesn't really add that much being called its own term. So I would propose reusing the `ID` term here. The only issue is that while hash works nicely as a Verb, ID does not. Personally I'd lean most towards `ID from Value`, but maybe there's a better name. Since I might also be misinterpreting the similarity of the terms I'd still like this to be signed off by the dev team. I'll put it on the agenda of the next meeting.
Author
Member

@SimonThommes I'm not opinionated on the Hash name so I'll leave this for the meeting. One thing to consider is if we add a Hash to Float node at some point that the naming fits in with this.

@SimonThommes I'm not opinionated on the Hash name so I'll leave this for the meeting. One thing to consider is if we add a `Hash to Float` node at some point that the naming fits in with this.
Member

We generally use X to Y instead of Y from X when naming nodes.

While I generally like "ID" here, it has one major problem for me. "ID" indicates uniqueness which a hashing function can't guarantee and there will inevitably be collisions where different input values map to the same output. A "hash" is less expected to be unique.

We generally use `X to Y` instead of `Y from X` when naming nodes. While I generally like "ID" here, it has one major problem for me. "ID" indicates uniqueness which a hashing function can't guarantee and there will inevitably be collisions where different input values map to the same output. A "hash" is less expected to be unique.
Hans Goudey requested changes 2024-01-30 04:57:11 +01:00
Hans Goudey left a comment
Member

I don't have a strong opinion on the name. I guess we should talk about it at a module meeting to make a final decision. Either way merge conflicts would need to be resolved before this is merged though.

I don't have a strong opinion on the name. I guess we should talk about it at a module meeting to make a final decision. Either way merge conflicts would need to be resolved before this is merged though.
Jacques Lucke added 2 commits 2024-02-26 13:07:05 +01:00
Member

Happy to confirm that this PR doesn't have the same floating point precision issue as the random value node (#118207) 👍

Happy to confirm that this PR doesn't have the same floating point precision issue as the random value node (#118207) 👍
Author
Member

Sorry, I've not been active on Blender for a while. Thanks for picking this up.

Sorry, I've not been active on Blender for a while. Thanks for picking this up.
First-time contributor

Hello ! Just wanted to say that these set of nodes could be useful indeed. I had a situation where I had to generate some indices for some elements (curves, points) and for now the only way was to use a random value node, which is fine but the hash function seems more straightforward to use and maybe will avoid some repetitions that I might ran into with the random node...

About the name, I found that Hash is better as it's basically what it is. If that was called ID I probably wouldn't have figured out what it is unless I looked into the manual.

Hello ! Just wanted to say that these set of nodes could be useful indeed. I had a situation where I had to generate some indices for some elements (curves, points) and for now the only way was to use a random value node, which is fine but the hash function seems more straightforward to use and maybe will avoid some repetitions that I might ran into with the random node... About the name, I found that Hash is better as it's basically what it is. If that was called ID I probably wouldn't have figured out what it is unless I looked into the manual.
Charlie Jolly added 1 commit 2024-08-28 12:09:49 +02:00
# Conflicts:
#	source/blender/blenkernel/BKE_node.hh
Charlie Jolly added 3 commits 2024-08-29 15:08:47 +02:00
Merge branch 'main' into gn-hash-node
Some checks failed
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
8b95addcd6
Author
Member

@blender-bot build

@blender-bot build
Charlie Jolly added 1 commit 2024-08-29 15:41:33 +02:00
Build fix - bNodeType
Some checks failed
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
ef8df1c43e
Author
Member

@blender-bot build

@blender-bot build
Charlie Jolly added 1 commit 2024-08-29 16:10:29 +02:00
Build fix - register bNodeType
All checks were successful
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
22fd76a300
Author
Member

@blender-bot build

@blender-bot build
Simon Thommes approved these changes 2024-08-29 16:39:53 +02:00
Simon Thommes left a comment
Member

To me this is good to go tbh 👍

Still wait for another checkmark by either Jacques or Hans for merging.

The only thing that could still be done imo is update supporting the matrix socket, but since it can also be separated into components and hashed that way this is not really a dealbreaker imo.

To me this is good to go tbh 👍 Still wait for another checkmark by either Jacques or Hans for merging. The only thing that could still be done imo is update supporting the matrix socket, but since it can also be separated into components and hashed that way this is not really a dealbreaker imo.
Author
Member

To me this is good to go tbh 👍

Still wait for another checkmark by either Jacques or Hans for merging.

The only thing that could still be done imo is update supporting the matrix socket, but since it can also be separated into components and hashed that way this is not really a dealbreaker imo.

There isn't currently a matrix hash function but could implement this as follows.

uint32_t hash_float(float4x4 k)
{
  return hash(hash_float(k.x), hash_float(k.y), hash_float(k.z), hash_float(k.w));
}
> To me this is good to go tbh 👍 > > Still wait for another checkmark by either Jacques or Hans for merging. > > The only thing that could still be done imo is update supporting the matrix socket, but since it can also be separated into components and hashed that way this is not really a dealbreaker imo. There isn't currently a matrix hash function but could implement this as follows. ``` uint32_t hash_float(float4x4 k) { return hash(hash_float(k.x), hash_float(k.y), hash_float(k.z), hash_float(k.w)); } ```
Iliya Katushenock reviewed 2024-08-29 17:57:39 +02:00
@ -1838,6 +1838,17 @@ static const EnumPropertyItem *rna_FunctionNodeRandomValue_type_itemf(bContext *
return itemf_function_check(rna_enum_attribute_type_items, random_value_type_supported);
}
static bool hash_value_type_supported(const EnumPropertyItem *item)

Unused.

Unused.
CharlieJolly marked this conversation as resolved
@ -0,0 +1,186 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors

Outdate license (23 -> 24).

Outdate license (`23` -> `24`).
CharlieJolly marked this conversation as resolved
@ -0,0 +2,4 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <cmath>

Unused include.

Unused include.
CharlieJolly marked this conversation as resolved
@ -0,0 +44,4 @@
node->custom1 = SOCK_INT;
}
static const mf::MultiFunction *get_multi_function(const bNode &bnode)

Swap get_multi_function and node_gather_link_searches things, just to less mix them/

Swap `get_multi_function` and `node_gather_link_searches` things, just to less mix them/
CharlieJolly marked this conversation as resolved
@ -0,0 +107,4 @@
};
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{

To handle Seed input and Hash output automatically:

static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
  const NodeDeclaration &declaration = *params.node_type().static_declaration;
  search_link_ops_for_declarations(params, declaration.inputs);
  search_link_ops_for_declarations(params, declaration.outputs);
To handle `Seed` input and `Hash` output automatically: ```Cpp static void node_gather_link_searches(GatherLinkSearchOpParams &params) { const NodeDeclaration &declaration = *params.node_type().static_declaration; search_link_ops_for_declarations(params, declaration.inputs); search_link_ops_for_declarations(params, declaration.outputs); ```
Author
Member

Left this for the moment as it did not work as expected with Boolean and String.

Left this for the moment as it did not work as expected with Boolean and String.
@ -0,0 +146,4 @@
{
RNA_def_node_enum(
srna,
"input_type",

Coud be data_type as in all other nodes?

Coud be `data_type` as in all other nodes?
CharlieJolly marked this conversation as resolved
Charlie Jolly added 2 commits 2024-08-29 18:40:54 +02:00
Address review
Some checks failed
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
9577155ff1
Author
Member
image
<img width="824" alt="image" src="attachments/ab6bff71-21e2-43e4-b1c2-ff7596aba778">
Author
Member

@blender-bot build

@blender-bot build
Charlie Jolly added 1 commit 2024-08-30 00:29:32 +02:00
lint error
All checks were successful
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
9d7aa939f7
Author
Member

@blender-bot package

@blender-bot package
Member

Package build started. Download here when ready.

Package build started. [Download here](https://builder.blender.org/download/patch/PR110769) when ready.
Jacques Lucke approved these changes 2024-08-30 13:02:05 +02:00

In convention with random value node, do we really need quaternion and matrix built-in support?\

In convention with random value node, do we really need quaternion and matrix built-in support?\
Member

@mod_moder

In convention with random value node, do we really need quaternion and matrix built-in support?

I don't think this comparison holds up here. The main issue imo with the random value node is that uniform distribution of these types is ill-defined and we'd need a more specialized node-group for that. I don't see that same issue with hashing

@mod_moder > In convention with random value node, do we really need quaternion and matrix built-in support? I don't think this comparison holds up here. The main issue imo with the random value node is that uniform distribution of these types is ill-defined and we'd need a more specialized node-group for that. I don't see that same issue with hashing
Hans Goudey approved these changes 2024-08-30 15:34:32 +02:00
@ -28,6 +29,7 @@ uint32_t hash_float(float kx);
uint32_t hash_float(float2 k);
uint32_t hash_float(float3 k);
uint32_t hash_float(float4 k);
uint32_t hash_float(float4x4 k);
Member

float4x4 is quite large and should be passed by const reference rather than by value. It has made a performance difference to do that in the past.

`float4x4` is quite large and should be passed by const reference rather than by value. It has made a performance difference to do that in the past.
CharlieJolly marked this conversation as resolved
Charlie Jolly added 1 commit 2024-08-30 15:57:18 +02:00
Pass float4x4 by const reference
All checks were successful
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
a58964b28e
Author
Member

@blender-bot build

@blender-bot build
Jacques Lucke merged commit 294994e4b9 into main 2024-08-30 16:42:48 +02:00
Charlie Jolly deleted branch gn-hash-node 2024-08-30 16:50:39 +02:00
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No Assignees
8 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#110769
No description provided.