Interpolation particles In Katana
I write the sphere radius interpolation for katana plugin that can transfer attributes,render attributes ,render velocity motion blur directly.
--GLY_MATH header source:
// // Created by gearslogy on 4/13/16. // #ifndef GLY_POINTSINTERPOLATION_GLY_COMMON_MATH_H #define GLY_POINTSINTERPOLATION_GLY_COMMON_MATH_H #include <stdlib.h> #include <string> #include <vector> #include <sstream> #define gly_rand_01 double(rand()) / double(RAND_MAX) namespace GLY_MATH { template <typename T> T min(T a,T b) { if(a>b) { return b; } else { return a; } } template <typename T> T max(T a,T b) { if(a>b) { return a; } else { return b; } } template <typename T> int zero_compare(T a, double tol=0.00001) { return a >= -tol && a <= tol; } // DO NOT USE THIS FIT TO FIT VECTOR VALUE template <typename T> T fit(T var, T omin, T omax,T nmin, T nmax) { T d = omax-omin; if(zero_compare(d)) { return (nmin+nmax)*0.5; } if(omin<omax) { if (var < omin) return nmin; if (var > omax) return nmax; } else { if (var < omax) return nmax; if (var > omin) return nmin; } return nmin + (nmax-nmin)*(var-omin)/d; } //return -1 to 1 template <typename T> T fit_negate(T var,T omin,T omax) { return fit(var,omin,omax,-1.0,1.0); } // fast random 01 var double random_01_value(int seed) { srand(seed); return gly_rand_01; } //string split std::vector <std::string> split_string(std::string &inputString, char &split_char) { std::stringstream ss(inputString); std::string sub_str; std::vector <std::string> sp_strPath; sp_strPath.clear(); while(getline(ss,sub_str,split_char)) { sp_strPath.push_back(sub_str); } return sp_strPath; } //value to string template <typename T> // T must be a value int/float/double std::string value_to_str(T &value) { std::ostringstream os; os<< value; return os.str(); } } #endif //GLY_POINTSINTERPOLATION_GLY_COMMON_MATH_H
--Arnold Source Code:
#include <ai.h> #include <stdio.h> #include <cstring> #include "GLY_common_math.h" #include <vector> #include <string> #include <omp.h> #include <assert.h> using namespace std; #define RAND_NORMALIZE float(rand()) / float(RAND_MAX) // global variables for read data //@pt_radius = point radius float pt_radius; //@pt_list_num = point interpolation num AtUInt32 pt_list_num; // float replicate_radius; AtArray *offset_vec; AtArray *frequency_vec; //motion blur param //@pt_use_vel_mb choose should use motion blur int pt_use_vel_mb; float shuffer_open_val; float shuffer_close_val; //exist attribute AtArray *id_array_list; //Katana particles id ->define named "ins_id" from houdini abc AtArray *pos_array_list; // Katana particles P ->define named "P" from houdini abc AtArray *vel_array_list; // other attribute string attribute_list; struct katana_attribute_map { string name; AtArray *map_array; //@map_array type = AI_TYPE_BYTE ->0 //@map_array type = AI_TYPE_INT ->1 //@map_array type = AI_TYPE_FLOAT ->4 //@map_array type = AI_TYPE_POINT ->8 }; vector <katana_attribute_map> att_maps; //get shuffer open pos AtVector get_shuffer_open_pos(AtVector &curl_v,AtVector &curl_p, float shuffer_open_val) { return curl_p+curl_v*shuffer_open_val; } // get shuffer close pos AtVector get_shuffer_close_pos(AtVector &curl_v,AtVector &curl_p, float shuffer_close_val) { return curl_p+curl_v*shuffer_close_val; } // this is set the constant radius static void setConstantRadius(AtArray *radius_array , float &rad) { #pragma omp parallel for for(int i=0;i<radius_array->nelements;i++) { AiArraySetFlt(radius_array,i,rad); } } //@shuffer_value may be open or close value //@cur_pos_array is the new pos from the interpolation array //@orig_velocity_array is from katana static AtArray* createMotionBlurOpenPoints(AtArray *orig_velocity_array, AtArray *cur_pos_array,float shuffer_value,AtUInt32 &iter_num) { AtInt32 num_pt = orig_velocity_array->nelements/3; printf("motion open ->get the num_pt is %d \n",num_pt); AtArray *_motion_points = AiArrayAllocate(cur_pos_array->nelements,1,AI_TYPE_POINT); vector <AtVector> large_vel_list; // THIS IS NOT SIMD PROGRAM /* for(AtUInt32 i=0;i<num_pt;i++) { AtVector __vel; __vel.x = AiArrayGetFlt(orig_velocity_array,i*3 + 0); __vel.y = AiArrayGetFlt(orig_velocity_array,i*3 + 1); __vel.z = AiArrayGetFlt(orig_velocity_array,i*3 + 2); for(int j=0;j<iter_num;j++) { large_vel_list.push_back(__vel); } } printf("motion open ->get the large vel array size is %d\n",large_vel_list.size()); printf("motion open ->get the pos array size is %d\n",cur_pos_array->nelements); */ large_vel_list.resize(iter_num * num_pt); // TELL THE GCC SIZE ,INDEX THE THREAD #pragma omp parallel for for(AtUInt32 i=0;i<num_pt;i++) { AtVector __vel; __vel.x = AiArrayGetFlt(orig_velocity_array,i*3 + 0); __vel.y = AiArrayGetFlt(orig_velocity_array,i*3 + 1); __vel.z = AiArrayGetFlt(orig_velocity_array,i*3 + 2); for(int j=0;j<iter_num;j++) { large_vel_list[i * iter_num + j ] = __vel; } } #pragma omp parallel for for(int i=0; i<large_vel_list.size();i++) { AtVector __vel = large_vel_list[i]; AtVector __pos = AiArrayGetPnt(cur_pos_array,i); AtVector __open_pos = get_shuffer_open_pos(__vel,__pos,shuffer_value); AiArraySetPnt(_motion_points,i,__open_pos); } return _motion_points; printf("motion open -> end\n "); } static AtArray* createMotionBlurClosePoints(AtArray *orig_velocity_array, AtArray *cur_pos_array,float shuffer_value,AtUInt32 &iter_num) { AtInt32 num_pt = orig_velocity_array->nelements/3; printf("motion open ->get the num_pt is %d \n",num_pt); AtArray *_motion_points = AiArrayAllocate(cur_pos_array->nelements,1,AI_TYPE_POINT); vector <AtVector> large_vel_list; /* for(AtUInt32 i=0;i<num_pt;i++) { AtVector __vel; __vel.x = AiArrayGetFlt(orig_velocity_array,i*3 + 0); __vel.y = AiArrayGetFlt(orig_velocity_array,i*3 + 1); __vel.z = AiArrayGetFlt(orig_velocity_array,i*3 + 2); for(int j=0;j<iter_num;j++) { large_vel_list.push_back(__vel); } }*/ //SIMD METHOD large_vel_list.resize(iter_num*num_pt); #pragma omp parallel for for(AtUInt32 i=0;i<num_pt;i++) { AtVector __vel; __vel.x = AiArrayGetFlt(orig_velocity_array,i*3 + 0); __vel.y = AiArrayGetFlt(orig_velocity_array,i*3 + 1); __vel.z = AiArrayGetFlt(orig_velocity_array,i*3 + 2); for(int j=0;j<iter_num;j++) { large_vel_list[i * iter_num + j] = __vel; } } #pragma omp parallel for for(int i=0; i<large_vel_list.size();i++) { AtVector __vel = large_vel_list[i]; AtVector __pos = AiArrayGetPnt(cur_pos_array,i); AtVector __close_pos = get_shuffer_close_pos(__vel,__pos,shuffer_value); AiArraySetPnt(_motion_points,i,__close_pos); } return _motion_points; printf("motion close -> end\n "); } //transfer the vector attribute to the replicate points static void fork_vector_attribute(AtArray *src_vector_array,AtArray *des_vector_array,AtUInt32 &iter_num) { float *src_vec_data = static_cast<float *> (src_vector_array->data); AtUInt32 src_num_pt = src_vector_array->nelements/3;// divide 3 because from Katana is a float array.. vector <AtRGBA> src_vec_list; src_vec_list.resize(src_num_pt * iter_num); #pragma omp parallel for for(AtUInt32 i=0; i<src_num_pt; i++) { AtRGBA __vec; __vec.r = src_vec_data[i*3 + 0]; __vec.g = src_vec_data[i*3 + 1]; __vec.b = src_vec_data[i*3 + 2]; __vec.a = 1.0f; for(int j=0;j<iter_num;j++) { //src_vec_list.push_back(__vec); src_vec_list[i*iter_num + j] = __vec; } } assert(src_vec_list.size() == des_vector_array->nelements); #pragma omp parallel for for(AtUInt32 i=0;i<src_vec_list.size();i++) { AiArraySetRGBA(des_vector_array,i,src_vec_list[i]); } } //transfer the float attribute to the replicate points static void fork_float_attribute(AtArray *src_float_array,AtArray *des_vector_array,AtUInt32 &iter_num) { float *src_flt_data = static_cast<float *>(src_float_array->data); AtUInt32 src_num_pt = src_float_array->nelements; vector <AtRGBA> src_vec_list; src_vec_list.resize(src_num_pt * iter_num); #pragma omp parallel for for(AtUInt32 i=0;i<src_num_pt; i++) { // convert float to the RGBA,"use_data_rgb/user_data_rgba" node get attribute in katana AtRGBA __vec; __vec.r = src_flt_data[i]; __vec.g = src_flt_data[i]; __vec.b = src_flt_data[i]; __vec.a = 1.0f; for(int j=0;j<iter_num;j++) { src_vec_list[i*iter_num + j] = __vec; } } assert(src_vec_list.size() == des_vector_array->nelements); #pragma omp parallel for for(int j=0;j<src_vec_list.size();j++) { AiArraySetRGBA(des_vector_array,j,src_vec_list[j]); } } //create point replicate static AtArray * makeSpherePoints(AtInt32 iter_num,AtInt32 orig_num_pt,AtArray *orig_pos_array,AtArray *orig_id_array) { AtVector _offset; _offset.x = AiArrayGetFlt(offset_vec,0); _offset.y = AiArrayGetFlt(offset_vec,1); _offset.z = AiArrayGetFlt(offset_vec,2); AtVector _frequency; _frequency.x = AiArrayGetFlt(frequency_vec,0); _frequency.y = AiArrayGetFlt(frequency_vec,1); _frequency.z = AiArrayGetFlt(frequency_vec,2); AtInt32 num_pt = iter_num * orig_num_pt; AtArray *_sphere_pos_array = AiArrayAllocate(num_pt,1,AI_TYPE_POINT); assert(orig_pos_array->type==4); // 4 is the AI_TYPE_FLOAT,because from katana P data is Array Float.... assert(orig_id_array->type==1); // 1 is the AI_TYPE_INT vector <AtVector> child_pt_pos_list; for(AtUInt32 i=0;i<orig_id_array->nelements;i++) { int _id = AiArrayGetInt(orig_id_array,i); AtVector orig_pos; orig_pos.x = AiArrayGetFlt(orig_pos_array,i*3 + 0); orig_pos.y = AiArrayGetFlt(orig_pos_array,i*3 + 1); orig_pos.z = AiArrayGetFlt(orig_pos_array,i*3 + 2); //printf("orig_pos_x -> : %f \n",orig_pos.x); //printf("orig_pos_y -> : %f \n",orig_pos.y); //printf("orig_pos_z -> : %f \n",orig_pos.z); for(int k=0;k<iter_num;k++) { AtVector pt; srand(_id * 5000 + k*1000+100); pt.x=GLY_MATH::fit(RAND_NORMALIZE,0.0f,1.0f,-1.0f,1.0f); srand(_id * 111000 + k*10000+10000); pt.y=GLY_MATH::fit(RAND_NORMALIZE,0.0f,1.0f,-1.0f,1.0f); srand(_id * 50000 + k*100000+100000); pt.z=GLY_MATH::fit(RAND_NORMALIZE,0.0f,1.0f,-1.0f,1.0f); //get offst //get frequency AtVector new_pt = AiVNoise3(pt*_frequency +_offset,4,0.0f,1.90f)*replicate_radius; //printf("the father %d,the child %d,noise_pos_x -> : %f \n",i,k,pt.x); //printf("the father %d,the child %d,noise_pos_y -> : %f \n",i,k,pt.y); //printf("the father %d,the child %d,noise_pos_z -> : %f \n",i,k,pt.z); child_pt_pos_list.push_back(new_pt + orig_pos); } } assert(child_pt_pos_list.size()==num_pt); #pragma omp parallel for for(AtUInt32 child=0;child<num_pt;child++) { AiArraySetPnt(_sphere_pos_array,child,child_pt_pos_list[child]); } return _sphere_pos_array; } static int pt_init(AtNode *node,void **user_ptr) { *user_ptr = node;// make a copy of the parent procudural //AtArray *pt_data_array = AiNodeGetArray(node,"point_data"); pt_list_num = AiNodeGetInt(node,"interpolationNum"); pt_radius = AiNodeGetFlt(node,"pointRadius"); pt_use_vel_mb = AiNodeGetInt(node,"use_vel_motion_blur"); shuffer_open_val = AiNodeGetFlt(node,"shuffer_open"); shuffer_close_val = AiNodeGetFlt(node,"shuffer_close"); // shape control replicate_radius = AiNodeGetFlt(node,"replicate_radius"); // Get id/pos list ... id_array_list = AiNodeGetArray(node,"ins_id"); pos_array_list = AiNodeGetArray(node,"P"); vel_array_list = AiNodeGetArray(node,"v"); offset_vec = AiNodeGetArray(node,"offset"); frequency_vec = AiNodeGetArray(node,"frequency"); attribute_list = AiNodeGetStr(node,"attributeTransferList"); /* for(int i=0;i<offset_vec->nelements;i++) { printf("get the offset val %f \n",AiArrayGetFlt(offset_vec,i)); } */ //printf("pt_init get the attribtue list is %s \n",attribute_list.c_str()); /* printf("get the type is %d \n",vel_array_list->type); for(int i=0;i<vel_array_list->nelements;i++) { printf("get the array is %f\n", AiArrayGetFlt(vel_array_list, i)); } */ char split_char = ','; vector <string > _attrib_list = GLY_MATH::split_string(attribute_list,split_char); att_maps.resize( _attrib_list.size() ); // SIMD SET ARRAY... #pragma omp parallel for for(int i=0; i<_attrib_list.size();i++) { string _curl_attrib_name = _attrib_list[i]; katana_attribute_map _map; _map.name = _curl_attrib_name; _map.map_array = AiNodeGetArray(node,_curl_attrib_name.c_str()); att_maps[i] = _map; } printf("pt_init get iter num particles is %d \n",pt_list_num); printf("pt_init get particles radius is %f \n",pt_radius); printf("pt_init get shuffer_open is %f \n", shuffer_open_val); printf("pt_init get shuffer close is %f \n", shuffer_close_val); printf("pt_init get the use_motion_blur is %d \n",pt_use_vel_mb); return true; } static int pt_cleanup(void *user_ptr) { return true; } static int pt_numnodes(void *user_ptr) { return 1; } static AtNode *MyGetNode(void *user_ptr,int i) { printf("create node\n"); AtNode *node = AiNode("points"); AtInt32 orig_num_pt = id_array_list->nelements; // from Houdini have num_pt AtInt32 iter_num_pt = orig_num_pt * pt_list_num; // every point have-> orig num pt * iterNum AtArray *pointArray = AiArrayAllocate(iter_num_pt,1,AI_TYPE_POINT); if(pt_use_vel_mb) { pointArray = AiArrayAllocate(iter_num_pt,2,AI_TYPE_POINT); } else { pointArray = AiArrayAllocate(iter_num_pt,1,AI_TYPE_POINT); } printf("start create pt\n"); AtArray *curl_pos_array = AiArrayAllocate(iter_num_pt,1,AI_TYPE_POINT); curl_pos_array=makeSpherePoints(pt_list_num,orig_num_pt,pos_array_list,id_array_list); if(pt_use_vel_mb) { printf("start create motion blur points\n"); AtArray *__open_pos_array = createMotionBlurOpenPoints(vel_array_list,curl_pos_array,shuffer_open_val,pt_list_num); AtArray *__close_pos_array = createMotionBlurClosePoints(vel_array_list,curl_pos_array,shuffer_close_val,pt_list_num); float *__open_pos_array_data = static_cast<float *> (__open_pos_array->data); float *__close_pos_array_data = static_cast<float *> (__close_pos_array->data); printf("setting motion blur points\n"); AiArraySetKey(pointArray,0,__open_pos_array_data); AiArraySetKey(pointArray,1,__close_pos_array_data); printf("setting motion blur points compelte\n"); } else { pointArray = curl_pos_array; } //Radius setttings //printf("starting create radius array\n"); AtArray *radiusArray = AiArrayAllocate(iter_num_pt,1,AI_TYPE_FLOAT); setConstantRadius(radiusArray,pt_radius); // transfer v attribute that can use "use_data_rgb/use_data_rgba" to render channel. AtArray *channel_v = AiArrayAllocate(iter_num_pt,1,AI_TYPE_RGBA); fork_vector_attribute(vel_array_list,channel_v,pt_list_num); AiNodeDeclare(node, "v", "uniform RGBA"); AiNodeSetArray(node,"v",channel_v); // transfer other transfer attribute for(int i=0; i<att_maps.size() ;i++) { katana_attribute_map map_attrib = att_maps[i]; string att_name = map_attrib.name; AtArray *array = map_attrib.map_array; AtArray *_channel = AiArrayAllocate(iter_num_pt,1,AI_TYPE_RGBA); AiNodeDeclare(node,att_name.c_str(),"uniform RGBA"); if(array->nelements == orig_num_pt) // not vector attrib { printf("fork other float/int attribute name is %s \n",att_name.c_str()); fork_float_attribute(array,_channel,pt_list_num); AiNodeSetArray(node,att_name.c_str(),_channel); } if(array->nelements == orig_num_pt *3 ) // vector attrib { printf("fork other vector attribute name is %s \n",att_name.c_str()); fork_vector_attribute(array,_channel,pt_list_num); AiNodeSetArray(node,att_name.c_str(),_channel); } } AiNodeSetArray(node,"points",pointArray); AiNodeSetArray(node,"radius",radiusArray); AiNodeSetStr(node, "mode", "sphere"); printf("complete the procedural points\n"); return node; } proc_loader { vtable->Init = pt_init; vtable->Cleanup = pt_cleanup; vtable->NumNodes = pt_numnodes; vtable->GetNode = MyGetNode; strcpy(vtable->version,AI_VERSION); return true; }
--KATANA Source code:
---header
// // Created by GearsLogy on 4/11/16. // this file connect the procedural points create ... // #ifndef GLY_INTERPOLATIONPARTICLES_GLY_INTERPOLATIONOP_H #define GLY_INTERPOLATIONPARTICLES_GLY_INTERPOLATIONOP_H #include <FnRenderOutputUtils/FnRenderOutputUtils.h> #include <FnGeolib/op/FnGeolibOp.h> #include <FnPluginSystem/FnPlugin.h> #include <FnAttribute/FnAttribute.h> #include <FnAttribute/FnGroupBuilder.h> #include <FnGeolib/util/Path.h> #include <FnGeolibServices/FnGeolibCookInterfaceUtilsService.h> class GLY_InterpolationOP : public Foundry::Katana::GeolibOp { public: static void setup(Foundry::Katana::GeolibSetupInterface &interface) { interface.setThreading(Foundry::Katana::GeolibSetupInterface::ThreadModeConcurrent); } static void cook(Foundry::Katana::GeolibCookInterface &interface); }; #endif //GLY_INTERPOLATIONPARTICLES_GLY_INTERPOLATIONOP_H
---source
/ // Created by gearslogy on 4/11/16. // #include "GLY_InterpolationOP.h" #include <stdio.h> #include <string> #include <vector> #include <sstream> using namespace std; void GLY_InterpolationOP::cook(Foundry::Katana::GeolibCookInterface &interface) { FnAttribute::StringAttribute get_par_loc = interface.getOpArg("particle_path"); FnAttribute::StringAttribute get_procedural_loc = interface.getOpArg("procedural_path"); if(!get_procedural_loc.isValid() || get_procedural_loc.getValue("",false).empty()) return; // next create a location just for the rendering... string procedural_loc_str = get_procedural_loc.getValue("",false); Foundry::Katana::CreateLocationInfo createLocationInfo; Foundry::Katana::CreateLocation(createLocationInfo,interface,procedural_loc_str); if(!get_par_loc.isValid()) { printf("%s not found the attribute",get_par_loc.getValue("", false)); return; } /* int ex = interface.doesLocationExist(get_par_loc.getValue("",false)); if(!ex) { printf("%s do not exist in the location\n",get_par_loc.getValue("", false)); return; }*/ string par_loc_str = get_par_loc.getValue("",false); FnAttribute::FloatAttribute get_par_radius_att = interface.getOpArg("pointRadius"); FnAttribute::IntAttribute get_par_num_att = interface.getOpArg("interpolationNum"); FnAttribute::IntAttribute get_use_motion_blur = interface.getOpArg("use_vel_motion_blur"); FnAttribute::FloatAttribute get_shuffer_open = interface.getOpArg("shuffer_open"); FnAttribute::FloatAttribute get_shuffer_close = interface.getOpArg("shuffer_close"); FnAttribute::FloatAttribute get_replicate_radius = interface.getOpArg("replicate_radius"); FnAttribute::FloatAttribute get_noise_fre = interface.getOpArg("frequency"); FnAttribute::FloatAttribute get_noise_offset = interface.getOpArg("offset"); FnAttribute::StringAttribute get_attribute_list = interface.getOpArg("attributeTransferList"); //printf("oparg check\n"); if(!get_par_radius_att.isValid()) return; if(!get_par_num_att.isValid()) return; if(!get_shuffer_open.isValid()) return; if(!get_use_motion_blur.isValid()) return; if(!get_shuffer_close.isValid()) return; if(!get_replicate_radius.isValid()) return; if(!get_attribute_list.isValid()) return; if(!get_noise_fre.isValid()) {printf("not found frequency arg\n");return;} if(!get_noise_offset.isValid()) {printf("not found offset arg\n");return;} //float pt_radius = get_par_radius_att.getValue(0.0f,false); //int pt_num = get_par_num_att.getValue(0,false); //printf("transfer data\n"); //get id and p attribute FnAttribute::IntAttribute id_attribute = interface.getAttr("geometry.arbitrary.ins_id.value",par_loc_str); FnAttribute::FloatAttribute pos_attribute = interface.getAttr("geometry.point.P",par_loc_str); FnAttribute::FloatAttribute vel_attribute = interface.getAttr("geometry.point.v",par_loc_str); if(!id_attribute.isValid()){ Foundry::Katana::ReportError(interface,"No ins_id attribute in particles location\n"); return; } if(!pos_attribute.isValid()){ Foundry::Katana::ReportError(interface,"No P attribute in particles"); return; } if(!vel_attribute.isValid()){ Foundry::Katana::ReportError(interface,"No v attribute in particles"); return; } string fullName = interface.getOutputLocationPath(); FnGeolibUtil::Path::FnMatchInfo fnMatchInfo; FnGeolibUtil::Path::FnMatch(fnMatchInfo, fullName,procedural_loc_str); if (!fnMatchInfo.match) return; //attribute transfer list checking string attr_list = get_attribute_list.getValue("", false); //printf("current attribute list is %s \n",attr_list.c_str()); stringstream ss(attr_list); string sub_str; vector <string> sp_strPath; sp_strPath.clear(); while(getline(ss,sub_str,',')) { sp_strPath.push_back(sub_str); } if(sp_strPath.size()!=0 && attr_list!="") { interface.setAttr("rendererProcedural.args.attributeTransferList",get_attribute_list); for(int i=0;i<sp_strPath.size();i++) { string __attri_base_name = sp_strPath[i]; string __prefix = "geometry.arbitrary."; string __endfix = ".value"; string __attri_des_name = __prefix + __attri_base_name + __endfix; //printf("checking the %s attribute\n",__attri_des_name.c_str()); FnAttribute::Attribute __att__handle = interface.getAttr(__attri_des_name,par_loc_str); int __att__type = __att__handle.getType(); // printf("the type is %d\n",__att__type); if(__att__handle.isValid()) { //printf("found attribute in particles %s\n",__attri_des_name.c_str()); if (__att__type == 1) // int { //printf("set to the int\n"); FnAttribute::IntAttribute __int_handle = FnAttribute::IntAttribute(__att__handle); interface.setAttr(string("rendererProcedural.args.")+ __attri_base_name , __int_handle); } if(__att__type == 2) // float { //printf("set to the float\n"); FnAttribute::FloatAttribute __float_handle = FnAttribute::FloatAttribute(__att__handle); interface.setAttr(string("rendererProcedural.args.")+ __attri_base_name , __float_handle); } } else { string error_msg = "please check the error attribute :" + __attri_base_name + " do not exist\n"; Foundry::Katana::ReportError(interface,error_msg); return; } } } // set our procedural attribute interface.setAttr("type",FnAttribute::StringAttribute("renderer procedural")); interface.setAttr("rendererProcedural.procedural",FnAttribute::StringAttribute("libArnoldGLY_PointInterpolation")); interface.setAttr("rendererProcedural.args.__outputStyle",FnAttribute::StringAttribute("typedArguments")); interface.setAttr("rendererProcedural.args.interpolationNum",get_par_num_att); interface.setAttr("rendererProcedural.args.pointRadius",get_par_radius_att); interface.setAttr("rendererProcedural.args.replicate_radius",get_replicate_radius); interface.setAttr("rendererProcedural.args.frequency",get_noise_fre); interface.setAttr("rendererProcedural.args.offset",get_noise_offset); // interface.setAttr("rendererProcedural.args.use_vel_motion_blur",get_use_motion_blur); interface.setAttr("rendererProcedural.args.shuffer_open",get_shuffer_open); interface.setAttr("rendererProcedural.args.shuffer_close",get_shuffer_close); interface.setAttr("rendererProcedural.args.ins_id",id_attribute); interface.setAttr("rendererProcedural.args.P",pos_attribute); interface.setAttr("rendererProcedural.args.v",vel_attribute); printf("katana Interpolation Particles -> setting complete\n"); }