Twist와 Bend Deformation의 중첩

7201 단어 HOUDINI

소개



안녕하세요. 후지 야마 타카시입니다. Houdini Apprentice Advent Calendar 2018 쪽에 빈 공간이 있는 것 같기 때문에 연속으로 새롭게 기사를 쓰게 해 주겠습니다. 어제 기사 아직 분은 좋으면 눈을 통해 봐 주세요.

이번에는 Wrangle for Loop을 사용하여 Twist와 Bend하는 방법을 소개하고 싶습니다.
벤드에 관해서는 다시 fujita님의 옛 기사 를 참고로 하겠습니다.
벤드는 단순한 변형입니다만 자력으로 할 수 있게 되면, 꽤 회전이나 삼각 함수등의 지식이 붙는다고 생각합니다.
그럼 잘 부탁드립니다.

함수 준비



먼저, 몇 가지 데모에 필요한 기능을 준비하고 싶습니다.

우선은 Rotation(회전)과 Translate(이동)의 매트릭스입니다.
표준이면 각각
matrix3 rot = ident();
rotate(rot, float angle, vector axis);

matrix4 tras = ident();
translate(trans, vector position);

라고 하는 식으로 한번 정의한 변수를 함수 안에 넣는 것으로 재계산됩니다.
단 2행이지만, 몇번이나 사용할 필요가 있으므로, 각각 1행으로 정의할 수 있는 함수로 합니다.
////function fn_rot////
matrix3 fn_rot(float r_val; vector axis){
    matrix3 rotM = ident();
    rotate(rotM, r_val ,normalize(set(axis)));
    return rotM;
}
////function fn_trans////
matrix fn_trans(vector position){
    matrix transM = ident();
    translate(transM, position);
    return transM;
}

이제 회전은 matrix3 rot = fn_rot(float angle, vector axis);이동은 matrix trans = fn_trans(vector position);로 정의할 수 있습니다.

다음은 Twist의 함수입니다.
트위스트 변형은 간단하고 기점에서 거리에 따라 회전시킬 뿐입니다.
트위스트의 축이 XYZ에 평행하지 않아도 dot product를 사용하면 축 방향으로의 거리를 낼 수 있습니다.
/////function fn_twist//////
matrix fn_twist(vector P, pivot, axis; float dist, angle){
    matrix twistM  = ident();
    twistM *= invert( fn_trans( pivot ));
    float dot = dot(normalize(axis),P*twistM);
    matrix horizonDir = twistM * invert( fn_trans( normalize(axis) * dot));
    float bendArea = fit(dot,0,dist,0,1);
    if(bendArea < 1){
        twistM *= fn_rot(angle * bendArea, axis);
    }else{
        twistM *= fn_rot(angle, axis);
    }
    twistM *= fn_trans( pivot );
    return twistM;
}



다음으로 벤드입니다.
이쪽도 세세한 곳은 생략합니다만 dot를 사용하는 것으로 구부리는 축의 거리를 내고 있습니다.
/////function fn_bend//////
matrix fn_bend(vector P, pivot, dir, axis; float dist, angle){
    matrix bendM  = ident();
    bendM *= invert( fn_trans( pivot ));
    float dot = dot(normalize(dir),P*bendM);
    matrix horizonDir = bendM * invert( fn_trans( normalize(dir) * dot));
    float bendArea = fit(dot,0,dist,0,1);
    if(bendArea < 1){
        bendM = horizonDir;
    }else{
        bendM *= invert( fn_trans(normalize(dir) * dist));
    }
    float angAmount = angle * min(dot,dist)/dist;
    float axisOffset = dist/angle;
    vector axisPos = normalize(cross(axis,dir)) * axisOffset;
    matrix3 rot = fn_rot(angAmount,normalize(axis) );
    if(bendArea > 0 && angle != 0){
        bendM = bendM * invert(fn_trans(axisPos)) * matrix(rot) * fn_trans(axisPos) * fn_trans(pivot);
    }else{
        bendM = ident();
    }
    return bendM;
}



함수를 사용해보십시오.



방금 전의 함수는 적당히 따로 Wrangle 노드를 준비해 거기에 두어 둡니다.
그리고 실제로 변형에 사용하는 Wrangle에서 그들을 참조합니다.

이렇게 하면 여러 노드에 걸쳐 함수를 공유할 수 있으며 작업 공간의 행 수를 줄일 수 있습니다.

그리고 방금 전의 함수를 사용하여 변형을 확인할 수있었습니다.

For Loop에 의한 겹침



그리고 이 트위스트와 벤드를 여러 개의 고유 파라미터를 곱해 가고 싶기 때문에 For Loop과 폴더 메뉴의 MultiParm과 조합합니다.

MultiParm은 fujita의 옛 만화에서도 언급되지만 폴더의 매개 변수는 parm1,parm2,parm3.....로 정의됩니다.
그래서 Wrangle 내 코드에서 그들을 참조하기 위해 For Loop 마다 참조처를 바꿉니다.
문자열의 끝에 숫자를 추가하려면 concat과 itoa를 사용하면 좋기 때문에ch(concat("parm",itoa(i)))입니다.

아래의 그림에서는 준비로서 간단히 MultiParm내에서 높이와 색을 참조해 발라가는 것을 만들었습니다.


트위스트 벤드 데폼도 이와 같이 했기 때문에 단계적으로 걸어 갑니다만, 데폼 했을 경우, 변형처로부터 위의 위치도 방향도 바뀌어 버리므로, 그 기점도 For Loop내에서 갱신 해 나가게 되므로, 사전에 pivot(기점), aim(방향), cross(축)라고 하는 변수를 준비해 둡니다.


그리고 최종 코드는 다음과 같습니다.

`chs("../fn/snippet")`

@rest = @P;

int iteration = chi("iteration");
vector pivot = set(0,0,0); 
vector aim = set(0,1,0);
vector cross = set(0,0,1);
float heightLimit = 0;

for(int i=1; i<=iteration; i++){
    float range = ch( concat("range", itoa(i)) );
    float twistAngle = ch( concat("twist", itoa(i)) );
    float bendAngle = ch( concat("bend", itoa(i)) );

    if(@rest.y > heightLimit){            
        @P *= fn_twist(@P, pivot, aim, range, twistAngle);

        @P *= fn_bend(@P, pivot, aim, cross, range, bendAngle);
    }

    vector tempPivot = pivot;
    tempPivot += aim * range;
    tempPivot *= fn_bend(tempPivot, pivot, aim, cross, range, bendAngle);
    pivot = tempPivot;
    matrix3 twistbend = fn_rot(twistAngle ,aim) * fn_rot(bendAngle ,cross);
    aim *= twistbend;
    cross *= twistbend;
    heightLimit += range;
}

이렇게 자유자재로 구부릴 수 있습니다.


아래의 값을 벤드와 트위스트에 곱해 애니메이션시켜 보았습니다.float valueAnim = clamp(@Frame/10 - i,0,0.6)/0.6;

파티클에 걸면 디폼의 흐름에 따라 파티클을 흘리는 것도 가능합니다.


작성한 파일은 이쪽이 됩니다.
h tps://d ゔぇ. 오, ぇ. 코 m/후에/d/18_g j0ly6gZc기우 436 8sV는 아코 FtjZc/ぃぃえw? 우 sp = 샤린 g

그럼 이번은 이상이 됩니다. 여기까지 읽어 주셔서 감사합니다!

좋은 웹페이지 즐겨찾기