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
View Code

--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 
",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
",large_vel_list.size());
    printf("motion open ->get the pos array size is %d
",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
 ");
}

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 
",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
 ");
}




//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 
",orig_pos.x);
        //printf("orig_pos_y -> : %f 
",orig_pos.y);
        //printf("orig_pos_z -> : %f 
",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 
",i,k,pt.x);
            //printf("the father %d,the child %d,noise_pos_y -> : %f 
",i,k,pt.y);
            //printf("the father %d,the child %d,noise_pos_z -> : %f 
",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 
",AiArrayGetFlt(offset_vec,i));
    }
     */
    //printf("pt_init get the attribtue list is %s 
",attribute_list.c_str());
    /*
    printf("get the type is %d 
",vel_array_list->type);
    for(int i=0;i<vel_array_list->nelements;i++) {
        printf("get the array is %f
", 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 
",pt_list_num);
    printf("pt_init get particles radius is %f 
",pt_radius);
    printf("pt_init get shuffer_open is %f 
", shuffer_open_val);
    printf("pt_init get shuffer close is %f 
", shuffer_close_val);
    printf("pt_init get the use_motion_blur is %d 
",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
");
    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
");
    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
");
        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
");
        AiArraySetKey(pointArray,0,__open_pos_array_data);
        AiArraySetKey(pointArray,1,__close_pos_array_data);
        printf("setting motion blur points compelte
");
    }
    else
    {
        pointArray = curl_pos_array;
    }

    //Radius setttings
    //printf("starting create radius array
");
    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 
",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 
",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
");
    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;
}
View Code


--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
View Code

---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
",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
");
    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
");return;}
    if(!get_noise_offset.isValid()) {printf("not found offset arg
");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
");
    //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
");
        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 
",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
",__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
",__att__type);
            if(__att__handle.isValid())
            {
                //printf("found attribute in particles %s
",__attri_des_name.c_str());
                if (__att__type == 1) // int
                {
                    //printf("set to the int
");
                    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
");
                    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
";
                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
");
}
View Code
原文地址:https://www.cnblogs.com/gearslogy/p/5421039.html