Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Vex

자잘한 팁

  • switch같은곳은 작아서 Ctrl+E로 확대해서 편집하자
  • if(a==b, 1, 2) 같은 식으로 넣을 수 도 있음.

Ramp이용한 프로파일

1번 오리지날

int point_arr[];

float profile = chramp("profile", 1);
int pointCount = chi("./profile");

for (int i = 1; i <= pointCount; ++i)
{
    float p_pos = ch("./profile" + itoa(i) + "pos");
    float p_val = ch("./profile" + itoa(i) + "value");
    int new_point = addpoint(0, set(p_pos, p_val, 0));
    append(point_arr, new_point);
}

addprim(0, "polyline", point_arr);

2번 - 간편

// 간편한 버전 Line - Resample 후
float perc = (float)@ptnum / (@numpt - 1);
float ramp = chramp("ramp", perc);
@P.y = y;

현재 노드 이름

string current_node_name = split(opfullpath("."), "/")[-1]; // $OS

라인에서 사이 각 구하기

int ptnum_prev;
int ptnum_next;

int ptnum_last = npoints(0) - 1;
if (@ptnum  == 0)
{
    ptnum_prev = ptnum_last;
    ptnum_next = 1;
}
else if (@ptnum == ptnum_last)
{
    ptnum_prev = ptnum_last - 1;
    ptnum_next = 0;
}
else
{
    ptnum_prev = @ptnum - 1;
    ptnum_next = @ptnum + 1;
}


vector pos_prev = point(0, "P", ptnum_prev);
vector pos_next = point(0, "P", ptnum_next);

vector dir_prev = normalize(@P - pos_prev);
vector dir_next = normalize(@P - pos_next);

float angle = degrees(acros(dot(dir_prev, dir_next)));

라인 방향 설정

// 일단 PolyFrame사용해서 Tangent:N 설정해주고,
// Wrangle(poitn)후 Visualize의 Marker&Vector로 right은 빨강, up은 초록

vector dir = @N;
dir.y = 0;
dir = normalize(dir);
v@right = cross(dir, {0, 1, 0});
v@up = cross(v@right, @N);

find_reveresed_prims

vector nrm = primuv(0, "N", @primnum, {0.5,0.5,0});
if(nrm.y < 0)
{
    i@group_reverse = 1;
}

0 ~ 1 구간 반복

float y = abs((x % 2) - 1);

엇갈려서 선을 이을때

//아니면 그냥 Connect Adjacent Pieces도 고려해볼것

vector p1_arr[];
for(int i = 0; i < npoints(0); i++)
{
    vector p1 = point(1, "P", i);
    append(p1_arr, p1);
}

for (int i = 0; i < npoints(0); ++i)
{
    int idx = i + 1;
    if (idx == npoints(0))
    {
        idx = 0;
    }

    vector p1 = p1_arr[idx];
    int newpt = addpoint(0, p1);
    addprim(0, "polyline", i, newpt);
}

return;

// 역방향일 경우
// - 위 vex에서 1번을 sort노드로 shift의 offset을 -1로
// - 아래 vex를 사용
for (int i = 0; i < npoints(0); ++i)
{
    int idx = i - 1;
    if (idx < -1)
    {
        idx = npoints(0) - 1;
    }

    vector p1 = p1_arr[idx];
    int newpt = addpoint(0, p1);
    addprim(0, "polyline", i, newpt);
}

선 - 연결선

  • 전깃줄같이 선 연결시 Vex로 안할 시 양끝단의 점에 bevel써주면 좋음
    • foreach를 돌고 끝단을 그룹핑하며 나중에 Bevel.
// vex: 전기선 v1
// ref: 3dbuzz - Houdini bridge contest - Houdini Bridge lesson09 cables 3 (10/13)
//     - https://www.youtube.com/watch?v=qIow2RgooII
// 현수교 같은곳에서 쓰면 됨.(양 끝점을 제어할 수 있음.)
// - line을 길게해서 놔두고 resample해서 사용.

float height = chf("height");
float valA = chf("valA");
float valB = chf("valB");
float arcVal = chf("arcVal");

float perc = @ptnum / (@numpt - 1.0f);

float x = valA * (1 - perc);
float y = valB * perc;
float z = -arcVal * (1 - perc) * perc;
float offsetPerc = x + y + z;

vector p = @P;
p.y = offsetPerc  * height;
@P = p;
// vex: 전기선 v2
// 전기선처럼 간편하게 사용할때.
// - 점 0 1 2로 이루어진 선에서 Group 1로 해서 1번 점만 내린다
// - 후에 Resample - Subdivision Curves로하면 글럴싸해짐

float seed1 = chf("seed");
float seed2 = chf("seed"); // detail(1, "iteration",0);
float min = chf("min");
float max = chf("max");
float amount = chf("amount");

float rand = rand(seed1, seed2);
float fit = fit01(rand, min, max);

@P.y -= (amount + fit);

선 - 현수선(catenary)

  • https://en.wikipedia.org/wiki/Catenary

  • https://lbcc.pressbooks.pub/structuraldesign/chapter/chapter-4-catenary-cables-and-arches-2/

  • y = a * cosh(x / a)

    • a : 스케일
    • x : 가로 위치
    • y : 세로 위치 ​
// vex: catenary v1
// primitive wrangle

int thesepoints[] = primpoints(0, @primnum);
vector startPos = point(0, "P", thesepoints[0]);
vector endPos = point(0, "P", thesepoints[1]);

int numPoints = 30;
float distance = distance(startPos, endPos);
float tension = chf("tension") * fit(rand(@primnum), 0, 1, 0.9, 1.3);

int pass = 0;
int newpoints[];
for (int i = 0; i <= numPoints; ++i)
{
    float t  = fit(i, 0, numPoints, -1, 1);
    float t2 = fit(i, 0, numPoints, 0, 1);
    float x  = t * distance;
    float y  = (cosh(x / tension) - 1) * tension;
    vector pointPos = lerp(startPos, endPos, t2);
    float baseline = (cosh(distance / tension) - 1) * tension; //offset at begining of curve
    pointPos.y += y - baseline;
    pass = addpoint(0, pointPos);
    append(newpoints, pass);
}
addprim(0, "polyline", newpoints);
removeprim(0, @primnum, 1);

hyperbolic cosine

// vex: catenary v2
// point wrangle
// ref: https://crudo.dev/docs/houdini-collection/catenary/

int numvtx = primvertexcount(0, @primnum);
float cuv = vertexcurveparam(0, @vtxnum);
float curve_length = primintrinsic(0, "measuredperimeter", @primnum);

float x = fit01(cuv, -curve_length / 2, curve_length / 2);
float random_seed = chf("random");
float a = chf("A") + (rand(@primnum + random_seed) - 0.5) * chf("random_amplitude");
a = max(a, 0.1);
float gain = chf("gain");

float y = -1 * gain * (a * cosh(x / a) - a * cosh(curve_length / (2 * a)));

v@P.y -= y;