最初に、VEXの定義をマニュアルで確認してみます。
float xyzdist(geometry, vector origin, int &prim, vector &uv, float maxdist)
マニュアルで上記でできることを確認すると以下のように記載されています。
originからジオメトリ上の一番近いポイントまでの距離を調べて、さらに一番近いポイントにおける
プリミティブ番号とUV座標を出力します。
重要なことは、最も近い実際のポイントを意味するのではなく、それらのポイントの間の補間されたプリミティブを意味することに注意してください。
次に定義で表示される "&"記号は、この関数がパラメータから読み込むのではなく、パラメータに書き込むことを意味します。
つまり、この関数に整数(入力ジオメトリのこと)とベクトルを供給すると、サーフェスまでの距離に加えて、プリミティブ番号とそのプリミティブのParametric UVも取得する事ができます。
Parametric UVとは?
下記にSideFXのPaulさんが説明されています。
Parametric Coordinates are similar to UV coordinates but cannot be modified, and always have a hardcoded value (see image above). This allows the mesh to be deformed without those “surface positions” changing. So as soon as we know at which Parametric Coordinate we want to “glue” something to on the original target mesh, we can later on look up where that surface position now is located in worldspace. We are going to exploit that in our Detail Mesh logic.
https://80.lv/articles/how-to-develop-effective-software-tools/
パラメトリック座標はUV座標に似ていますが、変更することはできず、常にハードコードされた値を持ちます。(上記の画像を参照)。 これにより、「surface positions(サーフェス位置)」が変化することなくメッシュを変形させることができます。 そこで、元のターゲットメッシュ上に「接着」したい「何か」のパラメトリック座標がわかればすぐに、そのsurface positions(サーフェス位置)から現在ワールドスペース内にある位置を調べることができます。
つまり、パラメトリックUVは通常のUVと同じではありません。取得した個々のプリミティブに対する正規化された位置を意味します。
xyzdist()の使い方
例えば下記のように1つのサーフェスがあります。
次にAddノードでポイントを作成し、Transformで移動できるようにします。Colorノードでポイントがわかりやすいように赤色を与えています。
その後、Attribute Wrangleノードを追加し、でポイントに対して下記のアトリビュートを追加します。各アトリビュートはそれぞれ下記の内容を格納することになります。
@d = 0; //originからジオメトリ上の一番近いポイントまでの距離 v@uv=0; //さらに一番近いポイントにおけるパラメトリックUV座標 i@pr=0; //さらに一番近いポイントにおけるプリミティブ番号
Geometry Spread Sheetで確認するとアトリビュートが追加されています。
更にAttribute Wrangleを追加し、Run OverはこれもPointにします。 入力0にBox、入力1にこのpigheadを接続します。
下記のコードを入力します。
float maxdist = 10; @d = xyzdist(1,@P,i@pr,v@uv,maxdist);
maxdistは検索する最大距離です。これを指定することで早期終了が可能になるので、この関数を高速化することができます。
この結果をGeometry spreadsheetで確認します。
これでポイントに一番近いポイントの距離、プリミティブ番号、parameteric uvを取得することができました。
もちろんこの値を取得したら何に使えるのかが気になる所です。この取得した結果を使用するときにprimuv()を使うことができます。