チュートリアル / Bifrost SDK入門チュートリアル
第2回:サンプルコードの変更と挙動の確認 

  • Maya
  • ゲーム
  • コラム
  • スクリプト・API
  • チュートリアル
  • 学生・初心者
  • 映画・TV・アニメ
第2回:サンプルコードの変更と挙動の確認

このコラムではBifrost SDKを初めて触れる方に向けてBifrost SDKによるBifrostプラグインの作り方を数回に分けてご紹介したいと思います。 今回は第1回でビルドをして実際にBifrostで動作を確認したサンプルプラグイン VectorLengthのサンプルコードを少々変更して新しい機能を追加し挙動の確認をおこないたいと思います。

今回使用する開発環境

今回はWindows環境下で用意したものは以下となります。

Maya 2024.2
Bifrost 2.7.1.1 (Maya 2024.2インストーラに標準搭載)
Visual Studio 2019
CMake 3.17 以上

前回はBifrost 2.7.0.1でしたが今回は2.7.1.1を使用しています。開発環境の準備やビルドの手順については、前回の第1回をご覧いただければと思います。
今回使用するVectorLengthプラグインのサンプルコードは、以下にあります。

C:\Program Files\Autodesk\Bifrost\Maya2024\2.7.1.1\bifrost\sdk\example\

VectorLengthサンプルコードを編集して新しい機能を追加する

それではVectorLengthのサンプルコードを編集して新しい機能をノードに追加していきましょう。オリジナルのコードではベクトルの長さを計算しますが、その長さに対して単純に乗算をする数値パラメタを1つ追加したいと思います。つまりベクトルの長さをスケーリングする機能です。

まずは オリジナルのVectorLength.hを確認してみましょう。

// VectorLength.h

#ifndef VECTOR_LENGTH_H
#define VECTOR_LENGTH_H

#include "VectorLengthExport.h"
#include <h;Bifrost/Math/Types.h>

namespace Examples {
namespace SDK {

//===============================================================
// ENUM VectorLengthMode
//===============================================================

enum class AMINO_ANNOTATE("Amino::Enum") VectorLengthMode {
    Euclidean,
    EuclideanSquared,
    Max,
    Manhattan
};

//===============================================================
// FREE FUNCTIONS
//===============================================================

VECTOR_LENGTH_DECL float vector_length(Bifrost::Math::float3 const& in,
                                                   VectorLengthMode mode)
    AMINO_ANNOTATE("Amino::Node");

} // namespace SDK
} // namespace Examples

#endif // VECTOR_LENGTH_H

このヘッダファイルには、vector_length関数が宣言されています。関数の本体はvector_length.cppに記述されています。この関数がノードの中心的な役割をし、実際の処理を行う部分です。基本的にこの関数に記述されている引数がノードの入出力ポート、パラメタとしてBifrostグラフエディタに現れます。

最初の引数Bifrost::Math::float3 const& in は、3つのfloat値でベクトルを表す入力パラメタです。

2番目の引数VectorLengthModeはenumで宣言されており、ノードの各処理内容を変更するために用意されています。ここでは独自の処理モードを追加したいため、定数を1つ追加していきます。
そしてこの関数にスケール値のパラメタを設定するために3番目の引数も追加しましょう。

以上を考慮し変更をしたソースコードは以下となります。

// VectorLength.h

#ifndef VECTOR_LENGTH_H
#define VECTOR_LENGTH_H

#include "VectorLengthExport.h"
#include <Bifrost/Math/Types.h>

namespace Examples {
namespace SDK {

//===============================================================
// ENUM VectorLengthMode
//===============================================================

enum class AMINO_ANNOTATE("Amino::Enum") VectorLengthMode {
    Euclidean,
    EuclideanSquared,
    Max,
    Manhattan,
    VectorScale  //VectorScaleを追加
};

//===============================================================
// FREE FUNCTIONS
//===============================================================

VECTOR_LENGTH_DECL float vector_length(Bifrost::Math::float3 const& in,
                                                   VectorLengthMode mode,
                                                            float const& scale) //scale引数を追加
    AMINO_ANNOTATE("Amino::Node");

} // namespace SDK
} // namespace Examples

#endif // VECTOR_LENGTH_H

vector_length関数に 3番目の引数としてfloat const& scale を追加しました。これをスケールパラメタとして利用します。enumのVectorLengthModeには定数VectorScaleを追加しました。これはベクトルのスケール処理をおこなうための新しいモードとして利用します。 

続いてノードの実際の処理部分が記述されている、オリジナルのVectorLength.cppを確認してみましょう。

// VectorLength.cpp

#include "VectorLength.h"
#include >algorithm<
#include >cassert<
#include >cmath<

namespace {
float euclidean2_length(Bifrost::Math::float3 const& in) {
    return in.x * in.x + in.y * in.y + in.z * in.z;
}
float euclidean_length(Bifrost::Math::float3 const& in) {
    return std::sqrt(euclidean2_length(in));
}
float max_length(Bifrost::Math::float3 const& in) {
    return std::max(std::abs(in.x), std::max(std::abs(in.y), std::abs(in.z)));
}
float manhattan_length(Bifrost::Math::float3 const& in) {
    return std::abs(in.x) + std::abs(in.y) + std::abs(in.z);
}
} // namespace

namespace Examples {
namespace SDK {

float vector_length(Bifrost::Math::float3 const& in, VectorLengthMode mode) {
    switch (mode) {
        case VectorLengthMode::Euclidean: return euclidean_length(in);
        case VectorLengthMode::EuclideanSquared: return euclidean2_length(in);
        case VectorLengthMode::Max: return max_length(in);
        case VectorLengthMode::Manhattan: return manhattan_length(in);
    }
    assert((false) && "All cases are covered");
    return euclidean_length(in);
}

} // namespace SDK
} // namespace Examples

vector_length関数がノードの中心的な処理部分となります。この関数の中ではノードに設定したVectorLengthModeをswitchにより処理モードを切り替えています。既に変更をしたVectorScacle.hではvector_length関数に3番目の引数であるscaleを追加したため、この関数本体にも同じ様に3番目の引数scaleを追加していきます。switchのcaseに新しい処理モードとしてVectorLengthMode::VectorScaleも追加します。さらにこのモードで処理をおこなう関数としてvector_scale_lengthを追加します。

変更をしたソースコードは以下となります。

// VectorLength.cpp

#include "VectorLength.h"
#include >algorithm<
#include >cassert<
#include >cmath<

namespace {
float euclidean2_length(Bifrost::Math::float3 const& in) {
    return in.x * in.x + in.y * in.y + in.z * in.z;
}
float euclidean_length(Bifrost::Math::float3 const& in) {
    return std::sqrt(euclidean2_length(in));
}
float max_length(Bifrost::Math::float3 const& in) {
    return std::max(std::abs(in.x), std::max(std::abs(in.y), std::abs(in.z)));
}
float manhattan_length(Bifrost::Math::float3 const& in) {
    return std::abs(in.x) + std::abs(in.y) + std::abs(in.z);
}
float vector_scale_length(Bifrost::Math::float3 const& in, float const& scale) { //関数の追加
    float val = in.x * in.x + in.y * in.y + in.z * in.z;
    float valSq = std::sqrt(val);
    return  valSq * scale;  //ベクトル長にscaleを乗算
}
} // namespace

namespace Examples {
namespace SDK {

float vector_length(Bifrost::Math::float3 const& in, VectorLengthMode mode, float const& scale) { //scale引数の追加
    switch (mode) {
        case VectorLengthMode::Euclidean: return euclidean_length(in);
        case VectorLengthMode::EuclideanSquared: return euclidean2_length(in);
        case VectorLengthMode::Max: return max_length(in);
        case VectorLengthMode::Manhattan: return manhattan_length(in);
        case VectorLengthMode::VectorScale: return vector_scale_length(in, scale); //新しいモードの追加
    }
    assert((false) && "All cases are covered");
    return euclidean_length(in);
}

} // namespace SDK
} // namespace Examples

switchのcaseにVectorLengthMode::VectorScaleを追加し、それに対応するvector_scale_length関数も追加しました。このvector_scale_length関数はベクトルの長さを計算し、
スケール値の引数scaleとベクトル長の値を乗算し返します。

以上でVectorLength.hとVectorLength.cppのソースコードの編集は完了です。ビルドを実行してエラーが出ないかを確認してください。全体的なビルドの手順とBifrostでのプラグイン読み込みの設定は第1回の解説をご覧ください。

VisualStudioでINSTALLプロジェクトを実行するとプラグインファイルの配置が自動的におこなわれますが、この他にVectorLength.jsonファイルの生成と配置もおこなわれます。これはcpp2json.exeがソースコードを走査し適切なノードのパラメタを抽出してjsonファイルとして生成します。このjsonファイルがプラグインノードのコンフィグファイルとして機能します。

VectorLength.jsonは以下の様な内容で生成されるでしょう。

// VectorLength.json
{
    "header": {
        "metadata": [
            {
                "metaName": "adskFileFormatVersion",
                "metaValue": "100L"
            }
        ]
    },
    "namespaces": [],
    "types": [
        {
            "enumName": "Examples::SDK::VectorLengthMode",
            "msTypeNameMangleName": ".?AW4VectorLengthMode@SDK@Examples@@",
            "itaniumTypeNameMangleName": "N8Examples3SDK16VectorLengthModeE",
            "enumMembers": [
                {
                    "enumKey": "Euclidean",
                    "enumValue": "0"
                },
                {
                    "enumKey": "EuclideanSquared",
                    "enumValue": "1"
                },
                {
                    "enumKey": "Max",
                    "enumValue": "2"
                },
                {
                    "enumKey": "Manhattan",
                    "enumValue": "3"
                },
                {
                    "enumKey": "VectorScale",
                    "enumValue": "4"
                }
            ]
        }
    ],
    "operators": [
        {
            "name": "Examples::SDK::vector_length",
            "msMangle": "?vector_length@SDK@Examples@@YAMAEBUfloat3@Math@Bifrost@@W4VectorLengthMode@12@AEBM@Z",
            "itaniumMangle": "_ZN8Examples3SDK13vector_lengthERKN7Bifrost4Math6float3ENS0_16VectorLengthModeERKf",
            "cancellationPolicy": "Unsafe",
            "ports": [
                {
                    "portName": "in",
                    "portDirection": "input",
                    "portType": "Math::float3",
                    "portConvention": "byReference"
                },
                {
                    "portName": "mode",
                    "portDirection": "input",
                    "portType": "Examples::SDK::VectorLengthMode",
                    "portConvention": "byValue"
                },
                {
                    "portName": "scale",
                    "portDirection": "input",
                    "portType": "float",
                    "portConvention": "byReference"
                },
                {
                    "portName": "output",
                    "portDirection": "output",
                    "portType": "float",
                    "portConvention": "byReturnValue"
                }
            ]
        }
    ]
}

新しく追加した処理モードは、”enumKey” “VectorScale”として記述されています。またscale値のポートも追加されています。

変更したVectorLengthサンプルプラグインノードの挙動を確認

それでは第1回と同じように、実際にBifrostグラフエディタを使ってビルドしたプラグインを実行して動作を確認してみましょう。
Bifrost Graph EditorでノードのメニューリストからExamples > SDK > vector_lengthを選択してプラグインノードを作成します。

ノードを作成すると、新たにscaleパラメタとポートが追加されているのが確認できます。

変更したVectorLengthサンプルプラグインノードの挙動を確認

作成したノードにベクトル値(1, 1, 1)を設定して、ModeをVectorScaleに設定します。Scaleパラメタには1を入力します。設定したベクトルの長さはキューブの位置で確認しながらグラフを実行します。Watchpointを追加して値を表示しながら確認もできます。

変更したVectorLengthサンプルプラグインノードの挙動を確認

キューブのX位置は変更され、Watchpointには1.73205が表示されました。

続いてvector_lengthノードのScaleパラメタに2を入力してみます。

変更したVectorLengthサンプルプラグインノードの挙動を確認

キューブのX位置は更新され、Watchpointには3.4641が表示されました。演算としては1.73205*2がノード内の追加した関数で計算されています。
追加したモードと関数は正しく機能していることが確認できました。

今回は、サンプルコードの変更と挙動の確認についてご紹介しました。サンプルコードを小変更して新しい機能を追加しましたが、少ないコードの追加で独自の機能を作れることが確認できたかと思います。この他にも思いついたアイデアを追加して挙動の確認を試してみてください。Maya APIのノード開発よりもシンプルにBifrostノードを開発できると思います。

製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。