先日HoudiniのVEX内におけるaddprim
とaddpoit
によって生成されるプリミティブやポイントの番号についての挙動に盛大に引っかかったので備忘録を兼ねた記事になります。
拙いVEXですがご容赦ください。
#実際に作ったもの
普通のgridから45度傾いた斜めのグリッドを生成しようとしていました
一番の上流になるため、copy系のノードを使わず、VEXで早く処理できないかと思い、基本的にはVEXで実装しました
結果とノードは以下のような感じです
2つのAttribute Wrangleでaddpoint
やaddprim
を使って、各プリミティブと外縁部ではないポイントそれぞれでプリミティブを生成してmergeしてfuseで繋げてる感じです
#addprimとaddpointで引っかかった挙動
基本的に今まではadd系のVEXを使う際はRun overをDetail(once only)にしていたので問題にはならなかったのですが、Run overをpointやprimitiveにし、同一Wrangle内で、その生成されたpointやprimitiveに対して操作を行いたい場合、各番号はどうなるのか、というところが問題となりました。
(後に使うaddvertex
ではターゲットとなるprimitiveやpointを番号で指定する必要があるため)
結論から書くと、Run overがprimitiveやpointであった場合、addprimやaddpointで生成される各要素の番号は、現在の@ptnumや@primnumのアトリビュートの数値の如何によらず、生成された順に、
@numprim + n
あるいは**@numpt + n
** となります。(n>=0)
#実際のノードでの実装
##from_prim
int maxiteration = primvertexcount(0,@primnum);
int ptoffset = @numpt;
int primoffset = @numprim;
vector posarray[];
int ptnumarray[];
for (int i=0; i<maxiteration; i++){
int linearvtx = vertexindex(0, @primnum, i);
int pt = vertexpoint(0, linearvtx);
ptnumarray[i]=pt;
vector pos = point(0,"P",pt);
posarray[i] = pos;
}
for (int j=0; j<maxiteration; j++){
int num = (j + 1)%maxiteration;
vector vtxpos1 = posarray[j];
vector vtxpos2 = posarray[num];
vector middlepos = (vtxpos1 + vtxpos2)/2;
addpoint(0,middlepos);
}
addprim(0,"poly");
for (int k=0; k<maxiteration; k++){
addvertex(0, primoffset ,ptoffset + k );
}
removeprim(0,@primnum,1);
プリミティブを構成する各ポイントの隣接する2頂点の中点に
addpoint
でポイントを生成し、addprim
で生成したプリミティブにaddvertex
で放り込む感じです
(汎用性を持たせるなら各エッジを起点に処理をしないといけないと思う)
##from_point
int primoffset = @numprim;
int ptoffset = @numpt;
if (neighbourcount(0,@ptnum)==4) {
int neighbourptnumarray[] = neighbours(0,@ptnum);
int num2 = neighbourptnumarray[2];
int num3 = neighbourptnumarray[3];
neighbourptnumarray[2] = num3;
neighbourptnumarray[3] = num2;
neighbourptnumarray = reverse(neighbourptnumarray);
addprim(0,"poly");
int maxiteration = len(neighbourptnumarray);
for(int i=0; i<maxiteration; i++){
vector pos1 = point(0,"P",neighbourptnumarray[i]);
vector pos = (@P + pos1)/2;
addpoint(0,pos);
addvertex(0,primoffset,ptoffset + i);
}
}
removepoint(0,@ptnum,1);
4つのポイントと隣接しているポイントに対し、それらと自身との各中点にポイントを生成してプリミティブを作成するというものです。
(途中明らかに汎用性が欠落する部分があるので要修正かなと思っています。)
各Wrangleでのaddvertex
では、ターゲットとする*prim_num
、point_num
がそれぞれ*@numprim + n
** あるいは**@numpt + n
** となっています
また、今回は自分自身の可読性を優先したため、primoffsetやらptoffsetと変数定義をしていますが、直接@numprimや@numptを使っても問題ありませんでした。
#余談
途中で作成し、実際にaddprimやaddpointの挙動の解決に至った際のものも置いておきます
各プリミティブの中心にポイントをインサートして、各エッジとつながる三角ポリゴンを生成するというものです
int maxiteration = primvertexcount(0,@primnum);
int ptoffset = @numpt;
int primoffset = @numprim;
vector posarray[];
int ptnumarray[];
for (int i=0; i<maxiteration; i++){
int linearvtx = vertexindex(0, @primnum, i);
int pt = vertexpoint(0, linearvtx);
ptnumarray[i]=pt;
vector pos = point(0,"P",pt);
posarray[i] = pos;
}
vector pointpos = avg(posarray);
addpoint(0,pointpos);
for (int j=0; j<maxiteration; j++){
int firstpt = ptoffset ;
int secondptindex = j;
int thirdptindex = (j+1)%4;
addprim(0,"poly");
addvertex(0, primoffset + j ,firstpt );
addvertex(0, primoffset + j , ptnumarray[secondptindex]);
addvertex(0, primoffset + j , ptnumarray[thirdptindex]);
}
removeprim(0,@primnum,0);
#サンプルファイル
一応サンプルファイルを置いておきます
https://drive.google.com/file/d/1r-GZVoat2Aur3kKrHbPeySNYYuXc8jwV/view?usp=sharing
間違いや質問のほか、もっと簡単に書いてやったぞ!みたいなのでもお気軽に!
#2021/10/24追記
intで変数宣言してからaddpointなりaddprimを行うことで、生成される要素の番号を戻り値として格納できるそうです。
というか公式のVEXドキュメントに普通に書いてありましたね、、、
int hoge = addpoint(0,pos);