slayerk Posted July 6, 2016 Share Posted July 6, 2016 (edited) 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 July 14, 2016 by slayerk Quote Link to comment Share on other sites More sharing options...
bonsak Posted July 11, 2016 Share Posted July 11, 2016 Hi Could you use the VEX function attribtype to check for datatype first? Then treat it accordingly? -b Quote Link to comment Share on other sites More sharing options...
slayerk Posted July 12, 2016 Author Share Posted July 12, 2016 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. Quote Link to comment Share on other sites More sharing options...
bonsak Posted July 12, 2016 Share Posted July 12, 2016 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 Quote Link to comment Share on other sites More sharing options...
haggi Posted July 12, 2016 Share Posted July 12, 2016 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. Quote Link to comment Share on other sites More sharing options...
bonsak Posted July 12, 2016 Share Posted July 12, 2016 That was my initial thought too but check the attached file. Setpointattrib() works fine with arrays. -b attributetype.hipnc Quote Link to comment Share on other sites More sharing options...
haggi Posted July 12, 2016 Share Posted July 12, 2016 You are right, it works in the example scene. Quote Link to comment Share on other sites More sharing options...
f1480187 Posted July 12, 2016 Share Posted July 12, 2016 (edited) 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 July 12, 2016 by f1480187 3 Quote Link to comment Share on other sites More sharing options...
slayerk Posted July 12, 2016 Author Share Posted July 12, 2016 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? Quote Link to comment Share on other sites More sharing options...
f1480187 Posted July 12, 2016 Share Posted July 12, 2016 Type info is handled already: addpointattrib(dst, name, defvalue, info) The last argument. Or what do you mean? Quote Link to comment Share on other sites More sharing options...
slayerk Posted July 12, 2016 Author Share Posted July 12, 2016 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. Quote Link to comment Share on other sites More sharing options...
f1480187 Posted July 12, 2016 Share Posted July 12, 2016 (edited) 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 July 12, 2016 by f1480187 Quote Link to comment Share on other sites More sharing options...
henderthing Posted April 23, 2019 Share Posted April 23, 2019 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)"); Quote Link to comment Share on other sites More sharing options...
f1480187 Posted April 26, 2019 Share Posted April 26, 2019 @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 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.