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;