Jump to content

How to handle unique attributes


Recommended Posts

I am trying to get the value of a string attribute, but it returns "0". I then noticed in the node info window that it was marked with "(4 unique)"

What is this "unique"? how to handle it? I am just trying to get the string value that is represented in the spreadsheet.

 

attrib_unique.PNG.ca2ff6a2aefa187c98787cf11f9ff6e1.PNG

Edited by bobbybob
Link to comment
Share on other sites

you have to provide more information 

trying to get a value how? where? there is so many different ways and contexts so it's difficult to know what you are trying. 

I'll take a stab in the dark and guess you are trying to use hscript prim() expression to get the string value of a particular prim, if that's the case you should use prims() expression as that will return value of a string parameter, prim() is for numeric values

 

unique means how many unique values of a given attribute there are among all the prims in your geometry 

so if you have 100 prims, but all of them have name attribute value "piece0", then it will show 1 unique

if some have value "piece0" and the rest "piece1", then those are 2 unique

if every primitive has different value of the same attribute, in other words if every prim's value is unique, then well, it will say 100 unique

  • Like 1
Link to comment
Share on other sites

Okay, that make sense :)

I am trying to get the string value via Vex, but the attributes returns "0" event that the spreadsheet shows the correct string value, so I thought the "unique" value was a way to inform about the size of some kind of custom array structure.

Link to comment
Share on other sites

So the answer is that the attribute are from geometry that is generated in another program, so the data type is not defined. I guess that Houdini is able to auto detect the type when it fetches the data to the spreadsheet, but the vex compiler are defaulting the data type to be a float.

The solution is to tell vex the type when using the attribute.

s@result = s@shop_materialpath;

 

Link to comment
Share on other sites

the fact that it is generated in another program is not the issue

but yes, you have to tell VEX what type to expect as that get's compiled into the code before it even runs on the geometry, so it already has to know what type it's going to work with

Link to comment
Share on other sites

Well, normally in programming you are defining the data type of variables when you declare them. Languages like HLSL and GLSL is a bit different then Vex that way. It's simply not possible to change the type when it's defined. I don't think that Houdini ever would create an attribute and not give it a type. If Houdini creates a string attribute, you can be sure that the type of that attribute are of the type string, so this problem will only emerge if you get data from outside Houdini or, you don't define your own attributes correct.

So no, "the fact that it is generated in another program is not the issue", but the issue will only arise when you get data from another program, or you write code that is not type safe yourself ;)

It would however be nice to get a warning if Houdini finds an attribute where no type is defined :)

Edited by bobbybob
Link to comment
Share on other sites

33 minutes ago, bobbybob said:

If Houdini creates a string attribute, you can be sure that the type of that attribute are of the type string, so this problem

right, but that doesn't mean that you can just read it without specifying that it's a string

43 minutes ago, bobbybob said:

so this problem will only emerge if you get data from outside Houdini 

not true

just use one wrangle: s@attrib1 = "myname";

followed by another wrangle node : @attrib2 = @attrib1;

attrib2 will be 0, since that wrangle will create attrib2 as float and also will look for float attrib1, which it will not find since attrib1 coming from the input is a string attribute, so you have to specify s@ in front of it if you want wrangle to be able to read it

some common attributes are hardcoded to default to certain type if you don's t specify it in front of @, like N, up, v, orient, name, id, ..., but custom ones or less common ones will default to float unless specifying otherwise

Link to comment
Share on other sites

2 hours ago, anim said:

right, but that doesn't mean that you can just read it without specifying that it's a string

This is actually pretty interesting, the attribute "shop_materialpath" (when generated in Houdini) is a string, if you pull the type info of the attribute via Vex, before you specific it's type, it will return that it is of type "string", but you cannot read from it before you define it's type... Houdini's Vex compiler reads the type just fine, but it still insist that the user define the type... Is there a deeper mening of this? From a programmers standpoint, it really just looks like the programmer who implemented this was a bit lazy? :/

You can try this yourself:

printf("Date type: %d\n", attribtype(0, "prim", "shop_materialpath"));

 

Edited by bobbybob
Link to comment
Share on other sites

it's how it works

you have to ask for an attribute of a specific type as you are using it in your code

it's like in many other programming languages

you are using the returned value, so when you read s@attrib you know that it will return string, if you ask @attrib you know it will return float (unless it's one of the common attributes, in that case you'd have to do for example f@name to bind to float name attrib)

otherwise, what would be a point of your code if what you get is a surprise? If you do 

float A = @attrib + 5;

what it will do now is it will look for float attribute named 'attrib', get its value and add 5 to it, if there is no incoming float attribute of that name @attrib will return 0 even if there is a strin or matrix or array or other type attribute named 'attrib'

if it was implemented as you suggest then what would you expect it to do if 'attrib' is string, matrix, array, vector, ...? that code would simply error out

 

EDIT: also note that you don't need to do this on all instances of @attrib binding in your code, if you use s@attrib first time you use @ binding in the wrangle, all other @ binding for the attribute in the same wrangle can just be @attrib and houdini will assume the same type

just inspect the resolved VEX code for your wrangle to really see to what your @ bindings resolve as a code, you will see that they just become arguments of your shader and they need to have defined type as any other shader or function

 

 

Edited by anim
Link to comment
Share on other sites

Hmm I am not completely sure what you are trying to say here. but let me try to explain.

I edited some of my ansvar out after I posted the last post, and I am not sure if you are replying to some of that, or it's just the part about defining the attribute that is already defined, but let me get back to that (It's normally not how it works)

When you declare an attribute, you have to define it's type, as you said yourself, if you don't define a type Houdini will default to float.

The type of the attribute will always be the same, as long as it lives. You don't need to specify the data type of an attribute when you wanna read from it, because it already has a data type.

When you talk about that you need to define what type you wanna read from an attribute, I can see why you think this way, and it can be a bit tricky even if you have tried to code in other languages. This is actually because of the way Houdini have implemented the attributes in vex, because it's syntax is a bit different.

When you do this:

s@a = s@b;

You are not asking to get value of "string" type from attribute b, you are actually declaring (creating) two attributes with the data type of string, and then giving "a" the value of "b"

You will never need to define the data type that you need to have returned to you from a attribute, so the surprise that you mentioned will never happen. You can always print the type of the attribute via vex or take a look at the "node info"

 

So back to the "shop_materialpath" issue. The thing here is not about the way programming works, or the vex compiler, I am talking about how the Houdini framework handle this. The string is defined as a string in Houdini. We have to "declare" it in vex, to read from it. That would make sense if vex could not see the attribute because it wasn't declared (declared in Houdini but not in vex), but we can still pull the data type of the attribute in vex without declaring it, you see, we can't pull the data type of an attribute that does not exist, and the datatype is returned, so when we then have to declare it again to read from it, it's a unnecessary step, you see?

If you declare the "shop_materialpth" attribute as a float, after you created it with a material node, and then pull it's type it will still return that it's a string. This is not because you have a attribute that have no data type, btw :P

Link to comment
Share on other sites

sounds like you are trying to explain to me how it works, while I thought I was explaining things to you

s@whatever creates new attribute only if the name is included in Attributes To Create and there is no attribute of the same name (with different type), otherwise only reads from it and even that only if the type matches, cause: 0.5*@whatever really wouldn't make sense if @whatever suddenly bound to 'whatever' attributes of any type, if incoming whatever attribute was string, it would be a surprise that I was talking about that the code didn't expect as the code wants to multiply the value with 0.5

but I believe this is something you have to get hands on more to understand

do some research what @ syntax in Snippet VOP actually is, how it resolves to VEX function with typed arguments, how that is used inside of actual shader, how that shader is compiled to something you can apply in many different contexts (in case of CVEX), how attributes, volumes, chop channels, ... are only bound to the shader if the name and the type matches, and how that shader uses defined default value if nothing binds to it, how you can use prototyping to define such default values etc...

then maybe it would make sense why specifying the type when using @ binding is important

 

Edited by anim
Link to comment
Share on other sites

So just to understand 100% Maybe I just don't understand the way Houdini has implemented vex, but it makes sense to you that we can create a material node, that create the attribute "shop_materialpath" of type string, and we from vex itself, at run time are able to access that attribute and get the type of that it?, but to read from it, we need to define it again? Because it makes absolutely no sense to me.

I am sure that you know Houdini much better then me. I know programming, and from a programmers standpoint it makes no sense do declare a variable that already exist...

Link to comment
Share on other sites

ok, just to get you going:

@ binding syntax itself doesn't have anything to do with attributes

this code in the wrangle (with default binding tab settings):

string A = s@myattrib;

produces VEX code equivalent to this (I just simplified to barebones as the auto generated code is more verbose):

cvex
myshader(string myattrib = "") {    
    string A = myattrib;
}

maybe now it resembles to you more what VEX truly is, strongly typed, non-object oriented programming language

you can see there is no assumption that myattrib is actually an attribute, there is no Attribute object in VEX (as it's not OO), but also this makes it universal, you can use the same shader in so many different contrexts, just bind the string argument to any string data, whether it is an attribute, or anything else that you may want to pass to is, but as you can see you had to define the type as that's how strongly typed languages work as you know

the fact that this can bind to an attribute data if this CVEX shader is run on geometry is to the fact that the program that runs the shader on the geometry can pass the attribute values as an argument of this shader.

this in houdini happens automatically when the attribute name and type matches the argument's name and type

so it's not that by using @ in the wrangle you are getting the attribute, you are merely defining the shader argument, to which the attribute will be bound if those conditions (name and type) are met, otherwise the value defined in the function argument assignment s used

obviously you can use Binding Tab on the wrangle to define which attribute will bind to which argument, but the type will still have to match in order for binding to happen

to see your auto generated VEX code, dive into the Wrangle, and on the attribvop1 do RMB/VEX_VOP_Options/View_VEX_Code...

 

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...