houdini vex header tips

avoid errors when header is included multiple times

always first line of your header:

#pragma once

or using

#ifndef __MY_HEADERNAME__
#define __MY_HEADERNAME__
// code here
#endif

function like define

#define print(v) printf("%g",v)

then using print instead of printf("%g",v)

using macro to create function which accepting different type argument

#pragma once

#define FUNCfoo(type)\
function void foo( const type val) {\
    printf("%g\n",val);\
}\

FUNCfoo(int)
FUNCfoo(float)

referenced document and article

houdini adding point to prim

adding a point to edge in prim

inside max, using maxscript we can easily add a vertex to an edge by using:
<index><EditablePoly>.insertVertexInEdge <index>edgeID <float>proportion
insert vertex to edge and return vertex id, so inside houdini, it's insert point to hedge and return point id.

vex doesn't has such function to add a point to edge, but it has function (addvertex) to add a point to prim.

let's start with adding point to prim at two different position.

// create points
addpoint(0,set(0,0,0));
addpoint(0,set(0,0,-1));
addpoint(0,set(1,0,0));
// create prim using points
int my_prim = addprim(0,"poly",0,1,2);

// create prim using points
int my_pt0 = addpoint(0,set(0.5,0,.1));
int my_pt1 = addpoint(0,set(0.6,0,-0.5));

// add point to prim
addvertex(0,my_prim,my_pt0);
// addvertex(0,my_prim,my_pt1);

add point to prim in different position

this vex create triangle like the one left image, and the point is been added to correct position like we want. but if we change the position of the new point, the result is not just like the one we want. that's because when we add a new point to a prim, houdini create a vertex id for the new point and push the id to the end of vertex array, so the order of point (vertex id) is "0-1-2-3" is same in two polygons. to make point order correct in second polygon, we need to change the order of point to "0-1-3-2".

int my_prim = 0;
int my_pt = 3;

// add point to prim
int my_vert = addvertex(geoself(),my_prim,my_pt);
// target edge defined by two point
vector2 target_points = set(1,2);

// get ordered point and vertex from prim 
int prim_points[]   = primpoints(geoself(),0);

// get position where to insert new point into
int insert_index = max(
    find(prim_points,target_points[0]),
    find(prim_points,target_points[1])
);

// put vertex into point array
insert(prim_points,insert_index,my_pt);

i@insert_index = insert_index;

// set prim vertex point
for(int i=insert_index;i<len(prim_points);i++){
    setvertexpoint(0,0,i,prim_points[i]);
}

now we can add point to prim between two point

function
void add_point_between_points(
    int geometry;
    int prim;
    int pt;
    int p0;
    int p1;
) {
    addvertex(geometry,prim,pt);

    vector pos = point(geometry,"P",pt);
    int prim_points[] = primpoints(geometry,prim);

    int insert_index = max(
        find(prim_points,p0),
        find(prim_points,p1)
    );
    insert(prim_points,insert_index,pt);

    for (int i=insert_index; i<len(prim_points); i++) {
        setvertexpoint(geometry,prim,i,prim_points[i]);
    }
}

make this function more maxscript style

function
int insertVertexInEdge(
        int geometry;
        int hedge;
        float proportion;
) {
    int src_pt = hedge_srcpoint(geometry,hedge);
    int dis_pt = hedge_dstpoint(geometry,hedge);
    vector src_pos = point(geometry,"P",src_pt);
    vector dis_pos = point(geometry,"P",dis_pt);
    // caculate position of new point
    vector pt_pos = src_pos + (dis_pos-src_pos)*proportion;

    // create a point
    int num_prim = hedge_equivcount(geometry,hedge);
    int pt = addpoint(geometry,pt_pos);

    // interpolate attributes to point
    string pt_attribs[] = detailintrinsic(geometry, "pointattributes");
    foreach(string pt_attrib;pt_attribs){
        if (pt_attrib=="P") continue;
        int attrib_type = pointattribtype(geometry,pt_attrib);
        if (attrib_type==0) {// int type
            int ited_value = point(geometry,"P",0);
            setpointattrib(geometry,pt_attrib,pt,ited_value);
        }
        else if (attrib_type==1) {// float and vector type
            int attrib_size = pointattribsize(geometry,pt_attrib);
            if (attrib_size==1)
                setpointattrib(geometry,pt_attrib,pt,float(lerp(point(geometry,pt_attrib,src_pt),point(geometry,pt_attrib,dis_pt),proportion)));
            else if (attrib_size==2)
                setpointattrib(geometry,pt_attrib,pt,vector2(lerp(point(geometry,pt_attrib,src_pt),point(geometry,pt_attrib,dis_pt),proportion)));
            else if (attrib_size==3)
                setpointattrib(geometry,pt_attrib,pt,vector(lerp(point(geometry,pt_attrib,src_pt),point(geometry,pt_attrib,dis_pt),proportion)));
            else
                setpointattrib(geometry,pt_attrib,pt,vector4(lerp(point(geometry,pt_attrib,src_pt),point(geometry,pt_attrib,dis_pt),proportion)));
        }
    }

    // add point to every prim which connected to hedge
    int cur_hedge = hedge_primary(geometry,hedge);
    for(int i=0;i<num_prim;i++){
        int prim = hedge_prim(geometry,cur_hedge);
        int prim_pts[] = primpoints(geometry,prim);

        addvertex(geometry,prim,pt);

        int insert_index = find(prim_pts,hedge_dstpoint(geometry,cur_hedge));
        insert(prim_pts,insert_index,pt);
        for (int ii=insert_index; ii<len(prim_pts); ii++) {
            setvertexpoint(geometry,prim,ii,prim_pts[ii]);
        }
        cur_hedge = hedge_nextequiv(geometry,cur_hedge);

    }

    return pt;
}

houdini oriented bounding box

basic process

  • caculate covariance matrix.
  • caculate eigenvalue and eigenvector using convaruance (we don't use eigenvalue in this case).
  • create bounding box.
    • under eigenvector or transform positions by eigenvector create AABB then transform bouding box using reverse eigenvector.

read more...