0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Houdini VEX】初心者向け 配列(Array)の基本とRun Overごとの扱い方

0
Last updated at Posted at 2026-07-07

はじめに

追記:{
    Attribute Promote SOPから配列を作る
}

🔰 Houdini初心者向けに、VEXの基礎を解説する記事を書いていきます。

本記事では、VEXを学ぶうえで最初に理解しておきたい 配列(Array)Run Over の基本について解説します。

配列はプログラミング全般で頻繁に使われる重要な概念であり、Run OverはHoudiniならではの実行方式です。この2つを理解することで、VEXのコードが格段に読みやすくなり、実践的な処理も書けるようになります。

初心者の方でも理解しやすいように、できるだけシンプルなサンプルコードを交えながら説明していきます。

image.png

配列とは?

image.png

配列(Array)とは、同じ種類のデータをまとめて管理するためのデータ型です。

例えば、果物の名前を複数扱いたい場合、次のように1つずつ変数を作ることもできます。

string fruit1 = "apple";
string fruit2 = "banana";
string fruit3 = "orange";
string fruit4 = "grape";

しかし、データが増えるたびに変数を増やす必要があり、管理が大変になります。

そこで配列を使うと、複数のデータを1つの変数にまとめることができます。

string fruits[] = {"apple", "banana", "orange", "grape"};

または、array() を使って書くこともできます。

string fruits[] = array("apple", "banana", "orange", "grape");

どちらも同じ意味なので、好きな書き方を使って構いません。

配列の中身を確認する

配列全体を表示してみます。

string fruits[] = {"apple", "banana", "orange", "grape"};

printf("%s\n", fruits);

出力

{"apple", "banana", "orange", "grape"}

要素を追加する

append() を使うと、配列の末尾に新しい要素を追加できます。

string fruits[] = {"apple", "banana", "orange", "grape"};

append(fruits, "strawberry");

printf("%s\n", fruits);

出力

{"apple", "banana", "orange", "grape", "strawberry"}

配列の要素を取り出す

配列の要素には、インデックスと呼ばれる番号でアクセスします。

配列の番号は 0から始まる ことに注意してください。

インデックス

0        1         2         3
┌───────┬────────┬────────┬───────┐
│ apple │ banana │ orange │ grape │
└───────┴────────┴────────┴───────┘

例えば、最初の要素を取得するには次のように書きます。

string fruits[] = {"apple", "banana", "orange", "grape"};

printf("%s\n", fruits[0]);

出力

apple

同様に、

printf("%s\n", fruits[1]);

なら

banana

が表示されます。

配列は 「同じ種類のデータを1つにまとめて管理するための箱」 と考えると理解しやすいでしょう。

この配列を for 文と組み合わせることで、データ数が増えても同じコードで効率よく処理できるようになります。

vector と vector4 の違い

VEXには、複数の数値を1つの変数として扱うための型が他にもあります。

vector

vector3つの float を持つデータ型です。

vector pos = set(1, 2, 3);

各要素には xyz でアクセスできます。

printf("%g\n", pos.x); // 1
printf("%g\n", pos.y); // 2
printf("%g\n", pos.z); // 3

vector4

vector44つの float を持つデータ型です。

vector4 value = set(0, 1, 2, 3);

4つ目の要素は w と呼ばれます。

printf("%g\n", value.x); // 0
printf("%g\n", value.y); // 1
printf("%g\n", value.z); // 2
printf("%g\n", value.w); // 3

また、配列のようにインデックスでもアクセスできます。

printf("%g\n", value[0]); // 0
printf("%g\n", value[1]); // 1
printf("%g\n", value[2]); // 2
printf("%g\n", value[3]); // 3

配列との違い

一見するとvectorvector4 は配列のように見えますが、別のデータ型です。

配列

float values[] = {0, 1, 2, 3};
  • 要素数を増減できる
  • append() が使える
  • 同じ型なら何個でも格納できる

vector4

vector4 value = set(0, 1, 2, 3);
  • 要素数は常に4つ
  • append() は使えない
  • 数学的な4次元ベクトルとして扱われる

つまり、

  • 配列は「データをたくさん保存するための入れ物」
  • vector / vector4は「座標や方向などを表すための固定長データ」

という役割の違いがあります。

配列とRun Over

複数のTestGeometryのノード名のtestgeometry_以下の文字列
をDetailクラスに配列として格納してみます
image.png

packしてMerge

ここでは分かりやすいように、Test GeometryをPackして一つのコンポーネントに
まとめてからMergeします。

その際Tranfer Attributesにshop_materialpathと入れてください
このpathからノード名を取り出します。

image.png

Mergeすると3つのprimだけになります。
分かりやすいようにNullをおいてOUT_Packsとしておきます。

image.png

豆知識

ノードを選択した状態で
ctrlキーを押しながらクリックで形や色を変更すると、
同じタイプのノードが一括で変更されます。

また、新規で同じタイプのノードを作った時にも、
その変更を受けた状態で作ることができます。
image.png

配列と Run Over

image.png
VEXで配列を扱うときは、Run Overの設定がとても重要です。

特に、複数のPrimitiveから値を集めて、1つの配列にまとめたい場合は、Run Over: Detail を使うのが基本です。


一番良い例:Run Over Detailで1回だけ実行する

// Run Over: Detail

string name_array[];

for (int i = 0; i < nprimitives(0); i++)
{
    string path = prim(0, "shop_materialpath", i);

    string slash[] = split(path, "/");
    string under[] = split(slash[2], "_");

    append(name_array, under[1]);
}

// detail配列アトリビュートとして保存
setdetailattrib(0, "name_array", name_array, "set");

foreach (string name; name_array)
{
    printf("%s\n", name);
}

Run Over: Detail は、Wrangleを1回だけ実行します。

そのため、全Primitiveを for 文で回して、取得した名前を1つの配列にまとめる処理に向いています。


配列にはなるが効率が悪い例:Primitiveで全Primitiveを回す

// Run Over: Primitives

string name_array[];

for (int i = 0; i < nprimitives(0); i++)
{
    string path = prim(0, "shop_materialpath", i);

    string slash[] = split(path, "/");
    string under[] = split(slash[2], "_");

    append(name_array, under[1]);
}

setdetailattrib(0, "name_array", name_array, "set");

これは一見動きますが、効率が悪いです。

Run Over: Primitives は、Primitiveの数だけWrangleを実行します。

例えばPrimitiveが100個ある場合、

Primitive Wrangleで100回実行
その中で for 文が100回実行

となるため、合計で

100 × 100 = 10,000回

処理されます。

つまり、同じ配列を何度も作って、detail属性に何度も上書きしている状態です。


意図通りの配列にならない例:Primitiveごとに配列が作られる

// Run Over: Primitives

string material_path = prim(0, "shop_materialpath", @primnum);

string slash[] = split(material_path, "/");
string underscore[] = split(slash[2], "_");

string name_array[];

append(name_array, underscore[1]);

printf("%s\n", name_array[0]);

setdetailattrib(0, "name_array", name_array, "set");

このコードでは、各Primitiveごとに name_array が作られます。

つまり、Primitiveが3つある場合は、内部的には次のようなイメージになります。

Primitive 0 → name_array = {"Body"}
Primitive 1 → name_array = {"Head"}
Primitive 2 → name_array = {"Arm"}

1つの配列に

{"Body", "Head", "Arm"}

と入るわけではありません。

Run Over: Primitives では、各Primitiveが個別に処理されるため、ローカル変数として作った配列はPrimitiveごとに別物になります。


まとめ

複数のPrimitiveから値を集めて、1つの配列にしたい場合は、

Run Over: Detail

を使うのが基本です。

一方で、Primitiveごとに個別の処理をしたい場合は、

Run Over: Primitives

を使います。

つまり、

全体で1つの配列を作る → Detail
各Primitiveごとに処理する → Primitives

と考えると分かりやすいです。

追記

Attribute Promote SOPから配列を作る

Array of Allのオプションを使うと配列が作れるのを教えて頂きました。
知らんかったー
image.png

shop_materialpathの配列が作られるので
ノード名だけを取り出してアトリビュートを上書きすると以下のようになります。

//run over detail

string name_array_renamed[];

string name_array[] = detail(0, "name_array");

foreach (string name; name_array){
    string slash[] = split(name, "/");
    string underscore[] = split(slash[2], "_");
    append(name_array_renamed, underscore[1]);
}

setdetailattrib(0, "name_array", name_array_renamed);
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?