Houdini VEX 學習筆記 (二)


//利用屬性分開Primitive

Primitive Split 節點中Attribute 設置為split 。Wrangle中代碼為:    f@split = @ptnum>10?1:4;

比較程序化的是利用Houdini 的Paint 節點,給物體描繪上顏色,然后利用顏色屬性把Primitive 分開


//曲線(在Vex中實現Carve節點的功能)

最近在做植物生長的rnd,期間生成了大量的curve,急需有能有個類似Carve節點的vex 函數,發現Vimeo上有大神用vex實現了這個功能(https://vimeo.com/104891696),后來在Odforce上看到,其實Houdini的Include文件中,有一個函數adjustPrimLength(在$HFS/houdini/vex/include/groom.h文件中定義)實現了這個功能,寫的極其簡潔,很美。具體代碼如下:

void adjustPrimLength(const int geo, prim; const float currentlength, targetlength)
{
    float diff = targetlength - currentlength;
    int points[] = primpoints(geo, prim);
    if(diff > 0)
    {
        vector posA = point(geo, "P", points[-2]);
        vector posB = point(geo, "P", points[-1]);
        vector posC = diff * normalize(posB-posA) + posB;
        int ptnum = addpoint(geo, posC);
        addvertex(geo, prim, ptnum);
    }
    else if(diff < 0)
    {
        vector lastpos = 0;
        float length = 0;
        int cut = 0;
        foreach(int idx; int pt; points)
        {
            vector pos = point(geo, "P", pt);
            if(idx > 0 && !cut)
            {
                float seglength = distance(pos, lastpos);
                if(length+seglength > targetlength)
                {
                    float frac = (targetlength-length)/seglength;
                    vector newpos = lerp(lastpos, pos, frac);
                    int ptnum = addpoint(geo, newpos);
                    for(int i=idx; i<len(points); i++)
                        removepoint(geo, points[i]);
                    addvertex(geo, prim, ptnum);
                    break;
                }
                length += seglength;
            }
            lastpos = pos;
        }
    }
}

在Houdini中的使用如下,首先每條Curve需要有一個屬性 @perimeter,記錄曲線的長度,這個屬性可以由Measure節點實現(Type設成Perimeter,Attribute設成perimeter)。然后下面接一個primitive wrangle 節點(Run Over設成Primitives),里面代碼如下:

#include <groom.h>
adjustPrimLength(0, @primnum, @perimeter, @perimeter*chf("dist"));

前后對比如下:

 實際應用中,應該把dist也設置成屬性,來更方便的控制:adjustPrimLength(0, @primnum, @perimeter, @perimeter*@dist);

//Pack 物體 ,傳遞Name屬性

利用pack 節點pack 物體后,把name從原來的primitive傳遞到point

s@name = primintrinsic(0, "fragmentname", @primnum);

 //VEX 隱藏屬性: primive的P屬性

新建一個Grid, 下面接一個point wrangle ,代碼如下:

@P = prim(0,"P",@primnum);

 再接一個 delete , 刪掉primitive,保留點,把之前的Grid template 顯示,可以看到點移到primitive 的中心去了,不過如果兩個面共享一個點時,這時這個點會跑到一個面的中心,但是對於Pack物體來說,就無所謂了,一個Primitive就對應一個點

 // Cone Twist Contraint 的配置

Primitive Wrangle

s@constraint_name = "cone";
s@constraint_type = "all";
v@constrained_twist_axis = @N;
v@constrained_up_axis = set(0,1,0);
v@goal_twist_axis = @N;
v@goal_up_axis = set(0,1,0);

 // 兩點組成的曲線

primitive wrangle

int pointindex(int prim; int vtx)
{
    return vertexpoint(geoself(), vertexindex(geoself(), prim, vtx));
}
int pt0 = pointindex(@primnum, 0);
int pt1 = pointindex(@primnum, 1);

f@restlength = distance(pt0,pt1);

  // 臨界邊

比較有意思,實現起來其實不難,想法比較好。先把Surface碎開,如下圖左。然后用Divide節點,勾選 Remove Shared Edges,圖中。

       

然后,Wrangle如下,把邊上的點刪掉,只留頂點,最后用Convertline轉成線,就得到一個簡單的鄰邊。

if(len(nearpoints(0,@P,0.0001))<3)
{
    removepoint(geoself(),@ptnum);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM