Houdini湖边小屋-屋顶细分详细过程记录

  b站UP主七里雪凝的湖边小屋教程——P3/P4【Houdini】萌新的《湖边小屋》教程拆解与实现,殊途同归!_哔哩哔哩_bilibili

目录

内容概括

详细步骤

1 [Facet节点]让每个ceiling面片拥有自己的points

2 [Attribute Wrangle节点]定义一些需要用到的属性

3 [Attribute Wrangle节点]划分branch面

3 [Attribute Wrangle节点]划分trunk面

4 [Attribute Wrangle节点]调整branch的trunk面

5 [Group Delete节点]删除不用的group

6 [Attribute Wrangle节点]划分每个roof面的level高度

用到的节点

1.facet节点

用到的VEX function

1.expandprimgroup

2.primpoints

3.getbbox

2.itoa

3.addpoint

4.set

5.setprimvertex


内容概括

把ceiling组的面片正确划分,为拉伸屋顶做准备。

详细步骤

1 [Facet节点]让每个ceiling面片拥有自己的points

用到了facet节点

2 [Attribute Wrangle节点]定义一些需要用到的属性

主要用到了Attribute Wrangle节点

教程中形象的用主干trunk和分支branch表示ceiling的面片地位,设定属性,与attribute create节点作用相同可以直接在attribute wrangle里用 i@...=... 来设定属性并赋予初始值。

初值设置为-1是为了与自动初值0分开来。

关于 Houdini中@定义属性的问题可以看看这篇文章:Houdini定义属性方式-CSDN

3 [Attribute Wrangle节点]划分branch面

这一步 Run Over 选择 Detail(only once) 让代码仅运行一次,以下是完整代码:

int pts[];
vector q0, q1, p1, p2, dir, tan;
vector src_minpos, src_maxpos, dst_minpos, dst_maxpos;
int ptnum1, ptnum2, new_prim, tri_prim1, tri_prim2;
int join_head, join_tail;
float width;

int prims[] = expandprimgroup(0, "ceiling"); //get all the prims
foreach(int main_prim; prims) { //use main_prim to get every prim_number as branch-prim
  pts = primpoints(0, main_prim); //get all points of main_prim
  getbbox(0, itoa(main_prim), src_minpos, src_maxpos); //get bounding box max&min, returns vectors
  foreach(int primnum; prims) {
    getbbox(0, itoa(primnum), dst_minpos, dst_maxpos); // get a prim as trunk-prim
    if(abs(src_minpos.y - dst_minpos.y) > 0.01) continue; // two prims should be in the same "y"
    q0 = point(0, "P", pts[0]);
    q1 = point(0, "P", pts[1]); //get two near points
    if(abs(src_minpos.z - dst_maxpos.z) < 0.01 || abs(src_maxpos.z - dst_minpos.z) < 0.01) {
      if((dst_minpos.x < src_minpos.x + 0.01) && (dst_maxpos.x + 0.01 > src_maxpos.x)){
        p1 = set((src_minpos.x + src_maxpos.x)/2.0, src_minpos.y, src_minpos.z);
        p2 = set((src_minpos.x + src_maxpos.x)/2.0, src_maxpos.y, src_maxpos.z);
        dir = abs(src_minpos.z - dst_maxpos.z) < 0.01 ? {0,0,-1} : {0,0,1};
        ptnum1 = addpoint(0, p1);
        ptnum2 = addpoint(0, p2);
        p1 = p1.zyx; //change z->x x->z
        p2 = p2.zyx;
        q0 = q0.zyx;
        q1 = q1.zyx;
      }else continue; // the primnum-prim can not be a trunk
      }else if (abs(src_minpos.x - dst_maxpos.x) < 0.01 || abs(src_maxpos.x - dst_minpos.x) < 0.01){
        if(dst_minpos.z - 0.01 < src_minpos.z && dst_maxpos.z + 0.01 > src_maxpos.z){
          p1 = set(src_minpos.x, src_minpos.y, (src_minpos.z + src_maxpos.z)/2);
          p2 = set(src_maxpos.x, src_maxpos.y, (src_minpos.z + src_maxpos.z)/2);
          dir = abs(src_minpos.x - dst_maxpos.x) < 0.01 ? {-1,0,0} : {1,0,0};
          ptnum1 = addpoint(0, p1);
          ptnum2 = addpoint(0, p2);
          }else continue;
        }else continue;

      int flag = abs(q0.x - q1.x) < 0.01;//flag =1,lineq0q1 is vertical to linep1p2
      if(abs(q0.x - p1.x) < 0.01){ //q0 and p1 are on the same "x"
      setprimvertex(0, main_prim, flag, ptnum1);
      setprimvertex(0, main_prim, flag + 1, ptnum2);
      new_prim = addprim(0, "poly", pts[flag], pts[flag + 1], ptnum2, ptnum1);
      tri_prim1 = addprim(0, "poly", pts[flag - 1], pts[flag], ptnum1);
      tri_prim2 = addprim(0, "poly", pts[flag + 1], pts[flag + 2], ptnum2);
      }else{ //q0 and p2 are on the same "x"
      setprimvertex(0, main_prim, flag + 0, ptnum2);
      setprimvertex(0, main_prim, flag + 1, ptnum1);
      new_prim = addprim(0, "poly", pts[flag], pts[flag + 1], ptnum1, ptnum2);
      tri_prim1 = addprim(0, "poly", pts[flag-1], pts[flag], ptnum2);
      tri_prim2 = addprim(0, "poly", pts[flag + 1], pts[flag + 2], ptnum1);
    }
      //tri_prim1 attributes
      setprimgroup(0, "triangle", tri_prim1, 1, "set");
      setprimattrib(0, "join_head", tri_prim1, -1, "set"); //initialvalue need to be set as "-1"
      setprimattrib(0, "join_tail", tri_prim1, -1, "set");
      setprimattrib(0, "trunk", tri_prim1, primnum, "set");
      setprimattrib(0, "heading", tri_prim1, dir, "set");
      setprimattrib(0, "twin", tri_prim1, -1, "set");
     
      //tri_prim2 attributes
      setprimgroup(0, "triangle", tri_prim2, 1, "set");
      setprimattrib(0, "join_head", tri_prim2, -1, "set");
      setprimattrib(0, "join_tail", tri_prim2, -1, "set");
      setprimattrib(0, "trunk", tri_prim2, primnum, "set");
      setprimattrib(0, "heading", tri_prim2, dir, "set");
      setprimattrib(0, "twin", tri_prim2, -1, "set");
      
      //set join_head and join_tail value
      join_head = dir.x + dir.z > 0.01 ? ptnum2 : ptnum1;
      join_tail = dir.x + dir.z > 0.01 ? ptnum1 : ptnum2;
      tan = point(0, "P", pts[flag - 1]) - point(0, "P", pts[flag]);
      width = length(tan)/2;
      
      //new_prim attributes
      setprimattrib(0, "N", new_prim, {0,1,0}, "set"); //normal
      setprimgroup(0, "roof", new_prim, 1, "set");
      setprimattrib(0, "twin", new_prim, main_prim, "set");
      setprimattrib(0, "trunk", new_prim, primnum, "set");
      setprimattrib(0, "dir", new_prim, dir, "set");
      setprimattrib(0, "join_head", new_prim, join_head, "set");
      setprimattrib(0, "join_tail", new_prim, -1, "set");
      setprimattrib(0, "width", new_prim, width, "set");
      
      //old prim main_prim attributes
      setprimgroup(0, "ceiling", main_prim, 0, "set"); //remove from group"ceiling"
      setprimgroup(0, "roof", main_prim, 1, "set"); // add to the newgroup "roof"
      setprimattrib(0, "twin", main_prim, new_prim, "set");
      setprimattrib(0, "trunk", main_prim, primnum, "set");
      setprimattrib(0, "dir", main_prim, dir, "set");
      setprimattrib(0, "join_tail", main_prim, join_tail, "set");
      setprimattrib(0, "width", main_prim, width, "set");

      setprimattrib(0, "branch", primnum, main_prim, "append");
      setprimattrib(0, "branch", primnum, new_prim, "append");
      break;
    }
  }

每一步的详细理解

//定义变量
//其中,以下所有涉及到判断的在>左边和<右边都会有0.01,来使判断更加精确
int pts[];
vector q0, q1, p1, p2, dir, tan;
vector src_minpos, src_maxpos, dst_minpos, dst_maxpos;//编号src在下面代表着branch的面上点,dst代表着trunk的面上点
int ptnum1, ptnum2, new_prim, tri_prim1, tri_prim2;
int join_head, join_tail;
float width;

int prims[] = expandprimgroup(0, "ceiling"); //得到group“ceiling”里所有面的面号
foreach(int main_prim; prims) { //用main_prim取循环提取prims数组中的每个面号
  pts = primpoints(0, main_prim); //得到面号为main_prim的面上的所有点号
  getbbox(0, itoa(main_prim), src_minpos, src_maxpos); //得到这个面的bounding box的最小点和最大点的坐标,点的类型是vector,这里用到itoa是把整型int转换成string为了拟合getbbox这个函数的用法规则
  foreach(int primnum; prims) {
    getbbox(0, itoa(primnum), dst_minpos, dst_maxpos);
    if(abs(src_minpos.y - dst_minpos.y) > 0.01) continue; //src和dst面至少要在同一个高度,也就是y要相同,如果不同 则跳出这层循环,继续找与src面匹配的dst面
    q0 = point(0, "P", pts[0]);
    q1 = point(0, "P", pts[1]); //这里的pts就是上面拿到的main_prim面上的点数组,得到点好为0和1的相邻点
    //以下是判断部分
    if(abs(src_minpos.z - dst_maxpos.z) < 0.01 || abs(src_maxpos.z - dst_minpos.z) < 0.01) {两个面是左右的关系
      if((dst_minpos.x < src_minpos.x + 0.01) && (dst_maxpos.x + 0.01 > src_maxpos.x)){
        p1 = set((src_minpos.x + src_maxpos.x)/2.0, src_minpos.y, src_minpos.z);
        p2 = set((src_minpos.x + src_maxpos.x)/2.0, src_maxpos.y, src_maxpos.z);
        dir = abs(src_minpos.z - dst_maxpos.z) < 0.01 ? {0,0,-1} : {0,0,1};
        ptnum1 = addpoint(0, p1);
        ptnum2 = addpoint(0, p2); //注意,set只是创建了vector,还需要addpoint来创建点
        p1 = p1.zyx; //change z->x x->z
        p2 = p2.zyx;
        q0 = q0.zyx;
        q1 = q1.zyx;
      }else continue; //说明trunk面在x轴方向上无法把branch面包含住,因此跳出这次循环,继续找下一个trunk面
      }else if (abs(src_minpos.x - dst_maxpos.x) < 0.01 || abs(src_maxpos.x - dst_minpos.x) < 0.01){
        if(dst_minpos.z - 0.01 < src_minpos.z && dst_maxpos.z + 0.01 > src_maxpos.z){
          p1 = set(src_minpos.x, src_minpos.y, (src_minpos.z + src_maxpos.z)/2);
          p2 = set(src_maxpos.x, src_maxpos.y, (src_minpos.z + src_maxpos.z)/2);
          dir = abs(src_minpos.x - dst_maxpos.x) < 0.01 ? {-1,0,0} : {1,0,0};
          ptnum1 = addpoint(0, p1);
          ptnum2 = addpoint(0, p2);
          }else continue;
        }else continue;//这个else是两个面的位置无论在左右还是上下方向上都不共边,因此两个面处于独立关系,重新找trunk面

      int flag = abs(q0.x - q1.x) < 0.01;//判断成立,则flag=1,说明线q0q1⊥p1p2 反之则q0q1∥p1p2
      if(abs(q0.x - p1.x) < 0.01){ //q0和p1在同一边
      setprimvertex(0, main_prim, flag, ptnum1);//移动面顶点的位置,但是顶点号的号码是不会变的
      setprimvertex(0, main_prim, flag + 1, ptnum2);
      new_prim = addprim(0, "poly", pts[flag], pts[flag + 1], ptnum2, ptnum1);
      tri_prim1 = addprim(0, "poly", pts[flag - 1], pts[flag], ptnum1);//侧边的面
      tri_prim2 = addprim(0, "poly", pts[flag + 1], pts[flag + 2], ptnum2);
      }else{ //q0和p2在同一边
      setprimvertex(0, main_prim, flag + 0, ptnum2);
      setprimvertex(0, main_prim, flag + 1, ptnum1);
      new_prim = addprim(0, "poly", pts[flag], pts[flag + 1], ptnum1, ptnum2);
      tri_prim1 = addprim(0, "poly", pts[flag-1], pts[flag], ptnum2);
      tri_prim2 = addprim(0, "poly", pts[flag + 1], pts[flag + 2], ptnum1);
    }
      //tri_prim1 attributes
      setprimgroup(0, "triangle", tri_prim1, 1, "set");
      setprimattrib(0, "join_head", tri_prim1, -1, "set"); //initialvalue need to be set as "-1"
      setprimattrib(0, "join_tail", tri_prim1, -1, "set");
      setprimattrib(0, "trunk", tri_prim1, primnum, "set");
      setprimattrib(0, "heading", tri_prim1, dir, "set");
      setprimattrib(0, "twin", tri_prim1, -1, "set");
     
      //tri_prim2 attributes
      setprimgroup(0, "triangle", tri_prim2, 1, "set");
      setprimattrib(0, "join_head", tri_prim2, -1, "set");
      setprimattrib(0, "join_tail", tri_prim2, -1, "set");
      setprimattrib(0, "trunk", tri_prim2, primnum, "set");
      setprimattrib(0, "heading", tri_prim2, dir, "set");
      setprimattrib(0, "twin", tri_prim2, -1, "set");
      
      //set join_head and join_tail value
      join_head = dir.x + dir.z > 0.01 ? ptnum2 : ptnum1;
      join_tail = dir.x + dir.z > 0.01 ? ptnum1 : ptnum2;
      tan = point(0, "P", pts[flag - 1]) - point(0, "P", pts[flag]);
      width = length(tan)/2;
      
      //new_prim attributes
      setprimattrib(0, "N", new_prim, {0,1,0}, "set"); //normal
      setprimgroup(0, "roof", new_prim, 1, "set");
      setprimattrib(0, "twin", new_prim, main_prim, "set");
      setprimattrib(0, "trunk", new_prim, primnum, "set");
      setprimattrib(0, "dir", new_prim, dir, "set");
      setprimattrib(0, "join_head", new_prim, join_head, "set");
      setprimattrib(0, "join_tail", new_prim, -1, "set");
      setprimattrib(0, "width", new_prim, width, "set");
      
      //old prim main_prim attributes
      setprimgroup(0, "ceiling", main_prim, 0, "set"); //remove from group"ceiling"
      setprimgroup(0, "roof", main_prim, 1, "set"); // add to the newgroup "roof"
      setprimattrib(0, "twin", main_prim, new_prim, "set");
      setprimattrib(0, "trunk", main_prim, primnum, "set");
      setprimattrib(0, "dir", main_prim, dir, "set");
      setprimattrib(0, "join_tail", main_prim, join_tail, "set");
      setprimattrib(0, "width", main_prim, width, "set");

      setprimattrib(0, "branch", primnum, main_prim, "append");
      setprimattrib(0, "branch", primnum, new_prim, "append");
      break;
    }
  }

3 [Attribute Wrangle节点]划分trunk面

完整代码,跟之前branch的方法差不多,这里就不过多解释了。

int pts[], ptnum1, ptnum2, new_prim, tri_prim1, tri_prim2, join_head, join_tail;
vector dir, q0, q1, p1, p2, src_minpos, src_maxpos, tmp_dir, tan;
int prims[] = expandprimgroup(0, "ceiling"); //get trunk prims
float width;
foreach(int trunk_prim; prims){
        pts = primpoints(0, trunk_prim);
        getbbox(0, itoa(trunk_prim), src_minpos, src_maxpos);
        int branch_prims[] = prim(0, "branch", trunk_prim);
        dir = 0;
        q0 = point(0, "P", pts[0]);
        q1 = point(0, "P", pts[1]);
        foreach(int branch_prim; branch_prims){
                dir += abs(prim(0, "dir", branch_prim));
        }
        if(dir.x > dir.z || abs(dir.z-dir.x) < 0.01 && src_maxpos.x-src_minpos.x < src_maxpos.z-src_maxpos.z+0.01){
                p1 = set((src_minpos.x+src_maxpos.x)/2, src_minpos.y, src_minpos.z);
                p2 = set((src_minpos.x+src_maxpos.x)/2, src_maxpos.y, src_maxpos.z);
                ptnum1 = addpoint(0, p1);
                ptnum2 = addpoint(0, p2);
                tmp_dir = {0,0,1}; //p1p2's direction.
                p1 = p1.zyx;
                p2 = p2.zyx;
                q0 = q0.zyx;
                q1 = q1.zyx;

        }else{
                p1 = set(src_minpos.x, src_minpos.y, (src_minpos.z+src_maxpos.z)/2);
                p2 = set(src_maxpos.x, src_maxpos.y, (src_minpos.z+src_maxpos.z)/2);
                ptnum1 = addpoint(0, p1);
                ptnum2 = addpoint(0, p2);
                tmp_dir = {1,0,0};

        }
        int flag = abs(q0.x - q1.x) <0.01;
        if(q0.x-p1.x <0.01){
                setprimvertex(0, trunk_prim, flag, ptnum1);
                setprimvertex(0, trunk_prim, flag+1, ptnum2);
                new_prim = addprim(0, "poly", pts[flag], pts[flag+1], ptnum2, ptnum1);
                tri_prim1 = addprim(0, "poly", pts[flag -1], pts[flag], ptnum1);
                tri_prim2 = addprim(0, "poly", pts[flag+1], pts[flag+2], ptnum2);
        }else{
                setprimvertex(0, trunk_prim, flag, ptnum2);
                setprimvertex(0, trunk_prim, flag+1, ptnum1);
                new_prim = addprim(0, "poly", pts[flag], pts[flag+1], ptnum1, ptnum2);
                tri_prim1 = addprim(0, "poly", pts[flag-1], pts[flag], ptnum2);
                tri_prim2 = addprim(0, "poly", pts[flag+1], pts[flag+2], ptnum1);
        }
        //tri_prim1 attributes
    setprimgroup(0, "triangle", tri_prim1, 1, "set");
    setprimattrib(0, "join_head", tri_prim1, -1, "set"); //initialvalue need to be set as "-1"
    setprimattrib(0, "join_tail", tri_prim1, -1, "set");
    setprimattrib(0, "trunk", tri_prim1, -1, "set");
    setprimattrib(0, "twin", tri_prim1, -1, "set");
      
    //tri_prim2 attributes
    setprimgroup(0, "triangle", tri_prim2, 1, "set");
    setprimattrib(0, "join_head", tri_prim2, -1, "set");
    setprimattrib(0, "join_tail", tri_prim2, -1, "set");
    setprimattrib(0, "trunk", tri_prim2, -1, "set");
    setprimattrib(0, "twin", tri_prim2, -1, "set");

    join_head = ptnum2;
    join_tail = ptnum1;
    tan = point(0, "P", pts[flag-1]) - point(0, "P", pts[flag]);
    width = length(tan)/2;

    //new_prim attributes
    setprimattrib(0, "N", new_prim, {0,1,0}, "set"); //normal 
      setprimgroup(0, "roof", new_prim, 1, "set");
      setprimattrib(0, "twin", new_prim, trunk_prim, "set");
      setprimattrib(0, "trunk", new_prim, -1, "set");
      setprimattrib(0, "branch", new_prim, branch_prims, "set");
      setprimattrib(0, "dir", new_prim, tmp_dir, "set");
      setprimattrib(0, "join_head", new_prim, join_head, "set");
      setprimattrib(0, "join_tail", new_prim, -1, "set");
      setprimattrib(0, "width", new_prim, width, "set");
      
      //old prim trunk_prim attributes
      setprimgroup(0, "ceiling", trunk_prim, 0, "set"); //remove from group"ceiling"
      setprimgroup(0, "roof", trunk_prim, 1, "set"); // add to the newgroup "roof"
      setprimattrib(0, "twin", trunk_prim, new_prim, "set");
      setprimattrib(0, "trunk", trunk_prim, -1, "set");
      setprimattrib(0, "dir", trunk_prim, tmp_dir, "set");
      setprimattrib(0, "join_tail", trunk_prim, join_tail, "set");
      setprimattrib(0, "width", trunk_prim, width, "set");
}

4 [Attribute Wrangle节点]调整branch的trunk面

这一步骤主要是因为一个trunk面会被划分成两个面,也就是有个twin面,之后要让branch对应的是原来的turnk还是trunk的twin对应的更精确。

Group 是 roof 和 triangle

这里的 Group Type 和 Run Over 都是 Primitive,也就是对于每个面都走一遍这个代码

vector src_minpos, src_maxpos, dst_minpos, dst_maxpos;
if(len(i[]@branch) == 0){ // this prim has no branch
        i[]@branch = prim(0, "branch", prim(0, "twin", @primnum)); //这个面的twin面的branch
} 
if(i@trunk >= 0){ //this prim has its trunk 
        getbbox(0, itoa(@primnum), src_minpos, src_maxpos);
        getbbox(0, itoa(i@trunk), dst_minpos, dst_maxpos);
        if(abs(dst_maxpos.z - src_minpos.z) < 0.01 || abs(src_maxpos.z - dst_minpos.z) <0.01){
                if(src_maxpos.x <dst_maxpos.x + 0.01 && src_minpos.x + 0.01 >dst_minpos.x){
                        return;//
                }
        }else if(abs(dst_maxpos.x - src_minpos.x) < 0.01 || abs(src_maxpos.x - dst_minpos.x) <0.01){
                if(src_maxpos.z <dst_maxpos.z + 0.01 && src_minpos.z + 0.01 >dst_minpos.z){
                        return;
                }
        }
        i@trunk = prim(0, "twin", i@trunk);//则trunk的twin成为当前branch面的真正的trunk
}
        

5 [Group Delete节点]删除不用的group

6 [Attribute Wrangle节点]划分每个roof面的level高度

这一步很重要,关系到后期拉高每个面的高度的步骤,建议自己看教程的P4部分

int roofs[], levels[];
int trunk, branch[], level, twin, init_level, cur;

void cut_loops(int trunk; int twin){ //提前规定一个函数,用来
        setprimattrib(0, "trunk", trunk, -1, "set");
        setprimattrib(0, "trunk", twin, -1, "set");
        setprimattrib(0, "join_head", trunk, -1, "set");
        setprimattrib(0, "join_head", twin, -1, "set");
        setprimattrib(0, "join_tail", trunk, -1, "set");
        setprimattrib(0, "join_tail", twin, -1, "set");
//^ 符号的作用:比较两个值如果相同则为0,如果不同则为1  
        int join_head, join_tail;
        join_head = -1 ^ prim(0, "join_head", trunk) ^ prim(0, "join_head", twin);
        join_tail = -1 ^ prim(0, "join_tail", trunk) ^ prim(0, "join_tail", twin);
        setpointattrib(0, "heading", join_head, {0,0,0}, "set");
        setpointattrib(0, "heading", join_tail, {0,0,0}, "set");

//delete branch
    int ttrunk = prim(0, "trunk", trunk);
    int ttwin = prim(0, "twin", trunk);
    int trunk_branch[] = prim(0, "branch", ttrunk);
    removevalue(trunk_branch, trunk);
    removevalue(trunk_branch, twin);
    setprimattrib(0, "branch", ttrunk, trunk_branch, "set");
    setprimattrib(0, "branch", ttwin, trunk_branch, "set");
        }
roofs = expandprimgroup(0, "roof");
resize(levels, max(roofs)+1);//change the array:levels[]'s size 
foreach(int pr; roofs){
    trunk = prim(0, "trunk", pr);//current_prim's trunk
        int count = 0;
        while(trunk != -1){ // if there is a loop include current_prim : 
            if(trunk == pr){ //find which prim's trunk is the first prim?
                push(loops, pr);//add prim-pr to array loops[];
                        break;
                }
                trunk = prim(0, "trunk", trunk);
                count ++;
                if(count >= len(roofs)) break;  
        }
} 
//now we have loops[], roofs[], levels[]
while(len(roofs)){
        trunk = pop(roofs, 0);//remove the prim at 0 and returns it
        push(roofs, trunk);//add trunk to the end of roofs[]
        branch = prim(0, "branch", trunk);
        if(len(branch) && len(roofs) > len(loops)) continue;
//we want to get a prim with no branch:
level = 0;
while(removevalue(roofs, trunk)){
        twin = prim(0, "twin", trunk);
        removevalue(roofs, twin);//do the same thing to the twin-prim
        if(removevalue(loops, trunk)){
                removevalue(loops, twin);
        }else{// this trunk-prim can be the next one when do the levelup
                level++;
                levels[trunk] = levels[twin] = level;
        }
        trunk = prim(0, "trunk", trunk);
        }
//get back to the first prim: 
if(trunk >=0 && level++ > levels[trunk]){
        init_level = levels[trunk];
        level = level - init_level; 
        cur = trunk;
        while(prim(0, "trunk", cur) != trunk){
//if init_level=0, levels[cur]=levels[cur]+level &&level++;
                levels[cur] += init_level ? level : level++;
                cur = prim(0, "trunk", cur);
        }
        levels[cur] += level;
        if(!init_level){
                twin = prim(0, "twin", cur);
                cut_loops(cur, twin);//cut the last prim in the loop
        }
}
}
for(int i=0;i<len(levels);i++){
        if(levels[i]){
                setprimattrib(0, "level", i, levels[i], "set");
        }
}

用到的节点

1.facet节点

Facet (sidefx.com)

Facet节点的主要作用是处理点或面的法线(normal)的相关操作,当导入一些杂乱的平面时facet可以用来整理(consolidate)平面的点和翻转的法线。

其中Unique Points选项可用来给所有面的顶点vertices创建自己的points,让面不共享points。

用到的VEX function

1.expandprimgroup

expandprimgroup (sidefx.com)

expandprimgroup(geometry, "groupname"); //其中groupname是个string类型,返回这个group里primitive的number,返回的是一个数组。

2.primpoints

primpoints (sidefx.com)

int [] primpoints(geometry, primnum);// 其中primnum是int类型的面号,返回面号为primnum的面里的所有点。

3.getbbox

getbbox (sidefx.com)

getbbox(geometry,&min,&max); // 得到这个几何体bounding box的最小边界值和最大边界值,这个&min和&max的类型是vector,也就是向量类型,目标检测中bounding box的VOC边框表示法就是(x_min,y_min,x_max,y_max),因此返回的值可以理解为点的坐标。

2.itoa

itoa (sidefx.com)

itoa(int类型的变量); //将整数转换成字符串string类型

3.addpoint

addpoint (sidefx.com)

addpoint(geometry,point_number); //创建一个跟点号为point_number具有相同属性和组关系的新点

addpoint(geometry,position); //后面的position是个vector,在几何体添加一个位置是position的点

4.set

set (sidefx.com)

vector2- set(v1,v2)

vector- set(v1,v2,v3)

... 创建一个vector或matrix(向量或矩阵)

5.setprimvertex

setprimvertex (sidefx.com)

把几何体的一个顶点vertex变成另一个不同的点

setprimvertex(geometry,prim,vertex_of_prim,point);// 把面prim上的顶点vertexofprim变成point,其中vertex_of_prim是面的顶点号

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九九345

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值