■ [Houdini]CEDEC2017で紹介されていたビルを作るHDA
回転対応などの汎用性を無視して、それっぽいものを実装してみる
特殊 等分割のほうは、「エッジなし」「エッジ半分」「エッジ両方」は未実装だけど、やっぱり必須だなぁ…。
3分割
string groupName = ch("groupName"); float sizeA = ch("Size_a"); float sizeB = ch("Size_b"); string groupNameA = ch("groupNameA"); string groupNameB = ch("groupNameB"); string groupNameC = ch("groupNameC"); float turn90 = ch("turn90"); if( groupName == "" || inprimgroup(@Opinput1,groupName,@primnum) == 1 ) { removeprim(geoself(), @primnum, 0); int points[] = primpoints(0, @primnum); int ip0, ip1, ip2, ip3; if( turn90 != 0 ){ ip0 = points[1]; ip1 = points[2]; ip3 = points[3]; ip2 = points[0]; }else{ ip0 = points[0]; ip1 = points[1]; ip3 = points[2]; ip2 = points[3]; } vector p0 = point(0, "P", ip0); vector p1 = point(0, "P", ip1); vector p2 = point(0, "P", ip2); vector p3 = point(0, "P", ip3); vector ap0 = p0 + normalize(p2-p0)*sizeA; vector ap1 = p1 + normalize(p3-p1)*sizeA; vector ap2 = p2 + normalize(p0-p2)*sizeB; vector ap3 = p3 + normalize(p1-p3)*sizeB; int iap0 = addpoint(geoself(), ap0); int iap1 = addpoint(geoself(), ap1); int iap2 = addpoint(geoself(), ap2); int iap3 = addpoint(geoself(), ap3); int prim; // Aプリミティブを生成 prim = addprim(geoself(), "poly"); addvertex(geoself(), prim, ip0); addvertex(geoself(), prim, ip1); addvertex(geoself(), prim, iap1); addvertex(geoself(), prim, iap0); if( groupName != "" ) setprimgroup(geoself(), groupName, prim, 1, "set"); setprimgroup(geoself(), groupName+"_"+groupNameA, prim, 1, "set"); // Bプリミティブを生成 prim = addprim(geoself(), "poly"); addvertex(geoself(), prim, iap2); addvertex(geoself(), prim, iap3); addvertex(geoself(), prim, ip3); addvertex(geoself(), prim, ip2); if( groupName != "" ) setprimgroup(geoself(), groupName, prim, 1, "set"); setprimgroup(geoself(), groupName+"_"+groupNameB, prim, 1, "set"); // Cプリミティブを生成 prim = addprim(geoself(), "poly"); addvertex(geoself(), prim, iap0); addvertex(geoself(), prim, iap1); addvertex(geoself(), prim, iap3); addvertex(geoself(), prim, iap2); if( groupName != "" ) setprimgroup(geoself(), groupName, prim, 1, "set"); setprimgroup(geoself(), groupName+"_"+groupNameC, prim, 1, "set"); }
特殊 等分割
string groupName = ch("groupName"); float sizeA = ch("sizeA"); float sizeB = ch("sizeB"); if( sizeB < 0.001 ) sizeB = 0.001; string groupNameA = ch("groupNameA"); string groupNameB = ch("groupNameB"); float turn90 = ch("turn90"); if( groupName == "" || inprimgroup(@Opinput1, groupName, @primnum) == 1 ) { removeprim(geoself(), @primnum, 0); int points[] = primpoints(0, @primnum); int ip0, ip1, ip2, ip3; if( turn90 != 0 ) { ip0 = points[0]; ip1 = points[1]; ip3 = points[2]; ip2 = points[3]; }else{ ip0 = points[1]; ip1 = points[2]; ip3 = points[3]; ip2 = points[0]; } // printf("[%d] %d,%d,%d,%d",@primnum,ip0,ip1,ip2,ip3); vector p0 = point(0, "P", ip0); vector p1 = point(0, "P", ip1); vector p2 = point(0, "P", ip2); vector p3 = point(0, "P", ip3); // 進行方向のベクトルを求める vector dirVec = normalize(p1-p0); // 幅を求める float width = distance(p1,p0); // 繰り返し回数を求める int rep = 1+width / (sizeA+sizeB); // 繰り返し回数の上限を設定 if( rep > 100 ) rep = 100; /* printf("w=%f\n",width); printf("a=%f\n",sizeA); printf("b=%f\n",sizeB); printf("rep=%d\n",rep); */ // sizeBをちょうどいい幅に補正 sizeB = (width - sizeA*rep) / rep; int prim; // 前の点のベクトル vector pp0 = p0; vector pp1 = p2; int ipp0 = addpoint(geoself(), pp0); int ipp1 = addpoint(geoself(), pp1); // 今追加したベクトル vector pn0, pn1; int ipn0, ipn1; for( int i=0; i// Aを追加 pn0 = pp0 + dirVec * sizeA; pn1 = pp1 + dirVec * sizeA; ipn0 = addpoint(geoself(), pn0); ipn1 = addpoint(geoself(), pn1); prim = addprim(geoself(), "poly"); addvertex(geoself(), prim, ipp0); addvertex(geoself(), prim, ipp1); addvertex(geoself(), prim, ipn1); addvertex(geoself(), prim, ipn0); if( groupName != "" ) setprimgroup(geoself(), groupName, prim, 1, "set"); setprimgroup(geoself(), groupName+"_"+groupNameA, prim, 1, "set" ); pp0 = pn0; ipp0 = ipn0; pp1 = pn1; ipp1 = ipn1; // Bを追加 pn0 = pp0 + dirVec * sizeB; pn1 = pp1 + dirVec * sizeB; ipn0 = addpoint(geoself(), pn0); ipn1 = addpoint(geoself(), pn1); prim = addprim(geoself(), "poly"); addvertex(geoself(), prim, ipp0); addvertex(geoself(), prim, ipp1); addvertex(geoself(), prim, ipn1); addvertex(geoself(), prim, ipn0); if( groupName != "" ) setprimgroup(geoself(), groupName, prim, 1, "set"); setprimgroup(geoself(), groupName+"_"+groupNameB, prim, 1, "set" ); pp0 = pn0; ipp0 = ipn0; pp1 = pn1; ipp1 = ipn1; } }