5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Houdini ApprenticeAdvent Calendar 2018

Day 12

トランスフォーマーロゴアニメーション

Posted at

#はじめに
あけましておめでとうございます。フジヤマタカシです。新年!ということでトランスフォーマー風のニューイヤーロゴを作りましたので、それについて軽く説明させて頂こうと思います。よろしくお願いします。

n0c45-jrqfr.gif

#ピースのセッティング
Screenshot from 2019-01-02 23-48-27.png
まずはdivideかなにかで分割します。

PrimWrangleでi@baseid = @primnum;としてbaseidを作ります。

Screenshot from 2019-01-03 00-22-02.png
コピーします。
コピーした後、PrimWrangleを使い下記のコードのpolyneighboursで隣接ポリゴンのプリミティブナンバーのリストを取得します。

i@primid = @primnum;
s@name = concat("piece",itoa(@primid));

i[]@neighbours = polyneighbours(0, @primnum); 

Screenshot from 2019-01-03 00-22-55.png

polyExtrudeで厚みをつけます。

Packした後にプリムアトリビュートのbaseidとneighboursをポイントにプロモートし,下記のコードでコピー先の軸にある隣接オブジェクトのナンバーを取得しneighboursに追加します・

string group = concat( "base_",itoa(i@baseid));
int moreNeighbours[] = pcfind(0, group, "P", @P, ch("radius"), 3);
moreNeighbours = moreNeighbours[1::];

append( i[]@neighbours, moreNeighbours );

ここまでの操作は隣接PackObjectのナンバーリストさえ取得できれば何でもいいです。

#階層セッティング
階層化は以前に書いた拡散していくボックスの方法に似ています。
Solver内で隣接オブジェクトをアクティブにしていきながら、処理させていった順にそのptnumのリストを追加していきます。この処理によって自身の親階層のリストを取得することになります。
Screenshot from 2019-01-03 00-57-54.png

Solver前に準備するアトリビュート。hierarchyに階層リストを格納します。

i@rootid = @ptnum;

if((rand(@ptnum + 123123)<0.6)){
    i@top = 1;
    i@connected = 1;
    
    i@level = 0;
    i[]@hierarchy = array(@ptnum);
    }

Solver内のコード、事前に準備していた隣接オブジェクトのナンバーを辿っていきます。

i@top = 0;

i[]@neighbours;
int unconnecteds[] = {};
foreach(int i; i[]@neighbours){
    if(point(0,"connected",i) == 0){
        append(unconnecteds,i);
    }
}

int active = 0;
if( len(unconnecteds) != 0 ){
    if(i@top == 1){
        active = 1;
    }else{
        if(rand(@ptnum+999 + @Frame) <  0.1 )active = 1;
    }
}

///select Next
if( active ){
    int selNex = floor( rand(@ptnum * 12 + @Frame) * len(unconnecteds) );
    int nextP = unconnecteds[selNex];
    
    setpointattrib(0, "top", nextP, 1);
    setpointattrib(0, "connected", nextP, 1);
    
    setpointattrib(0, "rootid", nextP, i@rootid);
    setpointattrib(0, "level", nextP, i@level + 1);
    int hierarchyPlus[] = i[]@hierarchy;
    append(hierarchyPlus, nextP);
    setpointattrib(0, "hierarchy", nextP, hierarchyPlus );
}

#マトリックス階層のアニメーション
階層トランスフォームは子の階層から親へ向かってかけていく必要があります。トランスフォームのマトリックスにはmaketransformを使います。簡単にPivotが設定できるからです。

matrix xform = ident();
for(int i=0; i<len(@hierarchy); i++ ){
    int index = @hierarchy[::-1][i];
    vector move;
    move[floor( rand(index + 11)*3 )] = fit01(rand(index + 110),-1,1) * 0.05; 
    vector rotation; 
    rotation[floor( rand(index + 22)*3 )] = rint( fit01(rand(index + 220),-1,1) * 3 ) * 90;
    vector pivot = point(0,"P",index);
    xform *= maketransform(0, 0, move, rotation, set(1,1,1), pivot);
}

@P *= xform;
setattrib(0, "primintrinsic", "transform", @primnum, -1, matrix3(xform), "set");

これが基本コード。int index = @hierarchy[::-1][i];で階層のナンバーを逆に辿ります。
indexを使ってランダムシードを使い。階層中心点はpoint(0,"P",index)で取得できます。

rottimingListとmovetimingListを精製して各階層のアニメーションタイミングを設定して並べただけのボックスを動かしてみます。

i[]@hierarchy;

float rottimingList[] = {};
float movetimingList[] = {};
float startFrame = 1;
for(int i=0; i<len(@hierarchy); i++ ){
    append(rottimingList, startFrame);
    startFrame += 2 + rand(@hierarchy[i] + 666) * 1;
    
    append(movetimingList, startFrame);
    startFrame += 4 + rand(@hierarchy[i] + 999) * 1;
}
matrix xform = ident();
for(int i=0; i<len(@hierarchy); i++ ){
    int index = @hierarchy[::-1][i];
    float rottiming = rottimingList[::-1][i];
    float movetiming = movetimingList[::-1][i];
    vector move;
    move [floor( rand(index + 11)*3 )] = rand(index + 111) * 1 * fit(@Frame,movetiming,movetiming + 5,1,0);
    vector rotation; 
    rotation[floor( rand(index + 22)*3 )] = floor( rand(index + 222) * 3 ) * 90 * fit(@Frame,rottiming,rottiming + 5,1,0);
    vector pivot = point(0,"P",index);
    xform *= maketransform(0, 0, move, rotation, set(1,1,1), pivot);
}

@P *= xform;
setattrib(0, "primintrinsic", "transform", @primnum, -1, matrix3(xform), "set");

ftqnj-9d4z1.gif
こんな感じです。このコードはほぼそのまま分画した立体ロゴに適応出来ます。多少調整したコードが下記のです。

i[]@hierarchy;

float rottimingList[] = {};
float movetimingList[] = {};
float startFrame = rand(@rootid + 333) * 20 + 1;
for(int i=0; i<len(@hierarchy); i++ ){
    append(rottimingList, startFrame);
    startFrame += 5 + rand(@hierarchy[i] + 666) * 5;
    
    append(movetimingList, startFrame);
    startFrame += 5 + rand(@hierarchy[i] + 999) * 15;
}

matrix xform = ident();
for(int i=0; i<len(@hierarchy); i++ ){
    int index = @hierarchy[::-1][i];
    float rottiming = rottimingList[::-1][i];
    float movetiming = movetimingList[::-1][i];
    vector move;
    move[floor( rand(index + 11)*3 )] = fit01(rand(index + 110),-1,1) * 0.05 * fit(@Frame,movetiming,movetiming + 5,1,0); 
    vector rotation; 
    rotation[floor( rand(index + 22)*3 )] = rint( fit01(rand(index + 220),-1,1) * 3 ) * 90 * fit(@Frame,rottiming,rottiming + 15,1,0);
    vector pivot = point(0,"P",index);
    xform *= maketransform(0, 0, move, rotation, set(1,1,1), pivot);
}

@P *= xform;
setattrib(0, "primintrinsic", "transform", @primnum, -1, matrix3(xform), "set");

n0c45-jrqfr.gif

作成したファイルはこちらになります。
https://drive.google.com/file/d/1If2sABdUx1ogkYMkiEh6PjcHMrDnBG-h/view?usp=sharing

フォントはこちらからダウンロードしましたが、サンプルファイルのテキストはフリーズさせてあります。
https://www.fontspace.com/category/transformers

では今回は以上になります。ここまで読んでいただきありがとうございます!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?