Jump to content

[SOLVED] Wrangle Node. Vex Problem with importing attribute.


slayerk

Recommended Posts

How can i import attribute to geoself() geometry from second input of wrangle node if i don't know type of this attribute.

I write function:

parameters:

native_input  = 0 (first input of wrangle node)

sample_input = 1 (second input of wrangle node)

attribs = string like "attrib1 attrib2 attrib3"

native_ptnum = number of point in current geometry where i want create attributes like in second input

sampled_ptnum = number of point from second input where i want sample attribute.

but cannon import any array attributes like "Cd" and etc...

This function correctly worked only if attribute is not array (type = 0 or 1 or 2) :(((

void sampleattribs(int native_input; int sample_input; string attribs; int native_ptnum; int sampled_ptnum ) {
    foreach(string aname; split(strip(attribs), " ")) {
        aname = strip(aname);
        if ( haspointattrib(sample_input, aname) ) {
            
            int atype = attribtype(sample_input, "point", aname);
            
            if (atype==0) {
                addpointattrib(native_input, aname, int(0));
                int value = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };
            if (atype==1) {
                addpointattrib(native_input, aname, float(0));
                float value = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };
            if (atype==2) {
                addpointattrib(native_input, aname, "");
                string value = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };
            if (atype==3) {
                int def_value[];
                addpointattrib(native_input, aname, def_value);
                int value[] = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };
            if (atype==4) {
                int size = pointattribsize(sample_input, aname);
                string typeinfo = attribtypeinfo(sample_input, "point", aname);
	                float def_value[] = {};
                for(int i=0; i<size; i++) append(def_value, 0.);
	                addpointattrib(native_input, aname, def_value);
                setattribtypeinfo(native_input, "point", aname, typeinfo);
                
                
                
                float value[];
                resize(value, size);
                int success = -1;
                
                //value = point(sample_input, aname, sampled_ptnum);
                //printf("%d\n", sampled_ptnum);
                
                //foreach(float v; value)  { printf("%f", v); };
                
                setpointattrib(native_input, aname, native_ptnum, value);
            };
            if (atype==5) {
                string def_value[]={};
                addpointattrib(native_input, aname, def_value);
                string value[] = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };
        };
    };
};
Edited by slayerk
Link to comment
Share on other sites

you read the code i'm attach above?

6th string is:

int atype = attribtype(sample_input, "point", aname);

problem is:

how to operate and create attributes of type: 3, 4, 5 (int, float, string arrays). code in my function doesn't work.

for example in array (type 3):

if (atype==3) {
                int def_value[];
                addpointattrib(native_input, aname, def_value);
                int value[] = point(sample_input, aname, sampled_ptnum);
                setpointattrib(native_input, aname, native_ptnum, value);
            };

simply creates int array with 1 element, independent to size of reference attribute array.

 

Link to comment
Share on other sites

Sorry about that. Thought i read through it all. Kind of hard to read black text on grey background. :)
Do you have a sample file you can upload that shows the problem? Or a call statement to your function with a sample of the data your passing in?
Or you could use Attribute Copy and set "Attribute Name" to asterix. That will basically do the same thing as your function is doing.

-b

Link to comment
Share on other sites

If I read the docs correctly, then the setpointattrib() function does not have an overloaded version which works on arrays. So I suppose you will have to iterate over the source entries and push them to the destination array.

Link to comment
Share on other sites

You did everything right, except misunderstanding about array and vector types. Cd is a float type with size of 3, not float array. Float array types are arrays of single floats as well as arrays of vectors or matrices.

attribute_copy.hipnc

Here I'm trying to be robust. With a bit more complex macro, it can be expanded to all types of geometry. You will see the current VEX limitations right in the code. I also simplified the code, so, you will need to wrap it in function and foreach loop again.

// Point wrangle.

// Testing variable set.
string name = "attrib";
int dst = geoself();
int dst_pt = @ptnum;
int src = 1;
int src_pt = dst_pt;

// Function body.
int type = pointattribtype(src, name);
int size = pointattribsize(src, name);
string info = pointattribtypeinfo(src, name);

#define ADDSETATTRIB(declaration)                \
{                                                \
    declaration = point(src, name, -1);          \
    addpointattrib(dst, name, defvalue, info);   \
    defvalue = point(src, name, src_pt);         \
    setpointattrib(dst, name, dst_pt, defvalue); \
}

// Any of it indicates attribute not exist on source.
if (type == -1 || size == 0 || info == "")
    error("Attribute not found");

// Integer.
else if (type == 0 && size == 1)
    ADDSETATTRIB(int defvalue)

// Float.
else if (type == 1 && size == 1)
    ADDSETATTRIB(float defvalue)

// 2-float vector.
else if (type == 1 && size == 2)
    ADDSETATTRIB(vector2 defvalue)

// 3-float vector.
else if (type == 1 && size == 3)
    ADDSETATTRIB(vector defvalue)

// 4-float vector or 2x2 matrix. Both are [4f] by default.
else if (type == 1 && size == 4)
    ADDSETATTRIB(vector4 defvalue)

// 3x3 matrix.
else if (type == 1 && size == 9)
    ADDSETATTRIB(matrix3 defvalue)

// 4x4 matrix.
else if (type == 1 && size == 16)
    ADDSETATTRIB(matrix defvalue)

// String.
else if (type == 2 && size == 1)
    ADDSETATTRIB(string defvalue)

// Integer array.
else if (type == 3 && size == 1)
    ADDSETATTRIB(int defvalue[])

// Float array.
else if (type == 4 && size == 1)
    ADDSETATTRIB(float defvalue[])

// String array.
else if (type == 5 && size == 1)
    ADDSETATTRIB(string defvalue[])

// Integer vectors.
else if (type == 0 && size > 1)
    error("Can't add %d-integer vector (Houdini 15.5)", size);

// Float vectors with arbitrary size.
else if (type == 1 && size != 2
                   && size != 3
                   && size != 4
                   && size != 9
                   && size != 16)
    error("Can't add %d-float vector (Houdini 15.5)", size);

// String vectors. Can be created by promoting varmap only.
else if (type == 2 && size > 1)
    error("Can't add %d-string vector (Houdini 15.5)", size);

// Integer vector arrays.
else if (type == 3 && size > 1)
    error("Can't add %d-integer vector array (Houdini 15.5)", size);

// Vector and matrix arrays.
else if (type == 4 && size > 1)
    error("Can't add %d-float vector array (Houdini 15.5)", size);

// We forgot something.
else
    error("Non-implemented for this kind of attributes");

// Impossible to get default attribute values in VEX in Houdini 15.5.
// We will stick to what point(input, attribute_name, -1) returns.
// And maybe in future it will return proper defaults, instead of zeros.
warning("Default values cannot be copied, if any. (Houdini 15.5)");
Edited by f1480187
  • Like 3
Link to comment
Share on other sites

Wow!!! Thanks!!!

More than anything, I'm afraid that for each type of data (returned by tipeinfo() function and each size of it) in Houdini would have to do a separate condition: (( No other, more simpler ways?

 

Link to comment
Share on other sites

yes, yes you right.

I mean I'm lazy and afraid that for each returned value of attribtypeinfo *(multiply) each size of attrib i must write separate if construction in code. :(((

I was hoping that there was an easier way.

Link to comment
Share on other sites

Could you post a working sample of VEX code implementing such separation? I think you don't have to do it at all. Type info is just a string passed into addpointattrib function, and it don't care about attribute size and even about actual type. Most of attributes have "none".

Edited by f1480187
Link to comment
Share on other sites

  • 2 years later...

Just coming here a few years later to say thanks for this! It's surprisingly difficult to make generalized tools that generate new primitives and cleanly inherit attributes from the incoming primitives. Also-- I've never seen this structure before in VEX (ADDSETATTRIB). Much cleaner than what I'd been doing...  Is there anywhere I can find documentation?

On 7/12/2016 at 6:07 AM, f1480187 said:

You did everything right, except misunderstanding about array and vector types. Cd is a float type with size of 3, not float array. Float array types are arrays of single floats as well as arrays of vectors or matrices.

attribute_copy.hipnc

Here I'm trying to be robust. With a bit more complex macro, it can be expanded to all types of geometry. You will see the current VEX limitations right in the code. I also simplified the code, so, you will need to wrap it in function and foreach loop again.


// Point wrangle.

// Testing variable set.
string name = "attrib";
int dst = geoself();
int dst_pt = @ptnum;
int src = 1;
int src_pt = dst_pt;

// Function body.
int type = pointattribtype(src, name);
int size = pointattribsize(src, name);
string info = pointattribtypeinfo(src, name);

#define ADDSETATTRIB(declaration)                \
{                                                \
    declaration = point(src, name, -1);          \
    addpointattrib(dst, name, defvalue, info);   \
    defvalue = point(src, name, src_pt);         \
    setpointattrib(dst, name, dst_pt, defvalue); \
}

// Any of it indicates attribute not exist on source.
if (type == -1 || size == 0 || info == "")
    error("Attribute not found");

// Integer.
else if (type == 0 && size == 1)
    ADDSETATTRIB(int defvalue)

// Float.
else if (type == 1 && size == 1)
    ADDSETATTRIB(float defvalue)

// 2-float vector.
else if (type == 1 && size == 2)
    ADDSETATTRIB(vector2 defvalue)

// 3-float vector.
else if (type == 1 && size == 3)
    ADDSETATTRIB(vector defvalue)

// 4-float vector or 2x2 matrix. Both are [4f] by default.
else if (type == 1 && size == 4)
    ADDSETATTRIB(vector4 defvalue)

// 3x3 matrix.
else if (type == 1 && size == 9)
    ADDSETATTRIB(matrix3 defvalue)

// 4x4 matrix.
else if (type == 1 && size == 16)
    ADDSETATTRIB(matrix defvalue)

// String.
else if (type == 2 && size == 1)
    ADDSETATTRIB(string defvalue)

// Integer array.
else if (type == 3 && size == 1)
    ADDSETATTRIB(int defvalue[])

// Float array.
else if (type == 4 && size == 1)
    ADDSETATTRIB(float defvalue[])

// String array.
else if (type == 5 && size == 1)
    ADDSETATTRIB(string defvalue[])

// Integer vectors.
else if (type == 0 && size > 1)
    error("Can't add %d-integer vector (Houdini 15.5)", size);

// Float vectors with arbitrary size.
else if (type == 1 && size != 2
                   && size != 3
                   && size != 4
                   && size != 9
                   && size != 16)
    error("Can't add %d-float vector (Houdini 15.5)", size);

// String vectors. Can be created by promoting varmap only.
else if (type == 2 && size > 1)
    error("Can't add %d-string vector (Houdini 15.5)", size);

// Integer vector arrays.
else if (type == 3 && size > 1)
    error("Can't add %d-integer vector array (Houdini 15.5)", size);

// Vector and matrix arrays.
else if (type == 4 && size > 1)
    error("Can't add %d-float vector array (Houdini 15.5)", size);

// We forgot something.
else
    error("Non-implemented for this kind of attributes");

// Impossible to get default attribute values in VEX in Houdini 15.5.
// We will stick to what point(input, attribute_name, -1) returns.
// And maybe in future it will return proper defaults, instead of zeros.
warning("Default values cannot be copied, if any. (Houdini 15.5)");
Link to comment
Share on other sites

@henderthing it's a preprocessor macro similar to ones in C language. Houdini 17.5 docs is not very informative on them. Fortunately, you can use C tutor on this: http://www.zentut.com/c-tutorial/c-macros/
We have both object and function macros in VEX. Be careful about:

...precedence

#define FOURv1 2 + 2
#define FOURv2 (2 + 2)

printf("8 == %d using FOURv1\n", FOURv1 * 2);  //  2 + 2  * 2
printf("8 == %d using FOURv2\n", FOURv2 * 2);  // (2 + 2) * 2

 

...more precedence

#define TWICEv1(arg)   arg  * 2
#define TWICEv2(arg)  (arg  * 2)
#define TWICEv3(arg) ((arg) * 2)

printf("8 == %d using TWICEv1\n", TWICEv1(1 + 1) * 2);  // Expanded as:   1 + 1  * 2  * 2
printf("8 == %d using TWICEv2\n", TWICEv2(1 + 1) * 2);  // Expanded as:  (1 + 1  * 2) * 2
printf("8 == %d using TWICEv3\n", TWICEv3(1 + 1) * 2);  // Expanded as: ((1 + 1) * 2) * 2

 

...scoping and line continuation

#define REPEATv1(arg) \
    arg;              \
    arg;

#define REPEATv2(arg) \
{                     \
    arg;              \
    arg;              \
}


if (0)
    REPEATv1(printf("This should never print (REPEATv1)."))

/*
Above expanded as:
if (0)
    printf("This should never print (REPEATv1).");
printf("This should never print (REPEATv1).");
*/


if (0)
    REPEATv2(printf("This should never print (REPEATv2)."))
/*
Above expanded as:
if (0)
{
    printf("This should never print (REPEATv1).");
    printf("This should never print (REPEATv1).");
}
*/

Note: you may want to omit the scope to generate variables that should be created in scope where macro is used.
And never put trailing space after backslash, as it will break the code with cryptic error.

 

For useful examples search VEX libraries in $HFS/houdini/vex/. For example, ADVECT_POINTS macro in $HFS/houdini/vex/include/groom.h at line 265

  • Thanks 1
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...