クリーチャーをセットアップする

クリーチャーをセットアップする方法について説明します。

手順 1: クリーチャーの略図を作成する

クリーチャーは、「チェーン」と「セクション」という 2 つのベース要素を組み合わせて構成されます。チェーンは手足(または触覚、尻尾、触手、下顎など)、または首や背骨などの 2 つのセクション間をつなぐリンクになります。セクションを持たないクリーチャーを作成することもできます(IK をそのボディ全体ではなく、手足にのみ実行する場合)。セクションは中枢的なボディ パーツです。それらはいくつかのチェーンの接合点と考えることができます。チェーンは完全に伸びた状態に達するとセクションを引き寄せる場合があります(「FullBodyIK」と呼ばれます)。

HumanIK は、各チェーンに対して 1 つのエフェクタを自動的に作成し、それをチェーンの末端に配置します(中間エフェクタはありません)。このエフェクタは、このチェーンを使用して到達したターゲットの位置と方向を定義します。

HumanIK はまた、各セクションに対して 1 つのエフェクタを作成します。このエフェクタは、このセクションを使用して到達したターゲットの位置と方向を定義します。

コードを作成する前に、チェーンとセクションを使ってクリーチャーの略図を書くことをお勧めします。サンプルに含まれているクリーチャーの略図を以下に示します。

通常、同じクリーチャーを実装するのにさまざまなオプションがあります。クリーチャーのどの部分をアニメートするか、どのようにアニメートするかに応じて、いろいろな組み合わせを選択して変化を付けることができます。次の図は、サンプルのクリーチャーのアニメーションをコントロールするために自動的に作成されるエフェクタを示しています。

手順 2: クリーチャーのチェーンのタイプを選択する

略図を書き終えたら、実際のチェーンのソルバ タイプを選択します。計算する付属器官のタイプ、期待する品質、CPU の制約などにもよりますが、1 つのチェーンのソルバ タイプを全体に適用すると良いでしょう。クリーチャーの 3D モデルに存在するジョイントの実際の数がこの選択に影響を与えることはありません。HumanIK に対してすべてのスケルトン ジョイントを宣言する必要はありません。スケルトン ジョイントのいくつかをスキップしても構いません。これはパフォーマンスを向上させる効果があります。たとえば、5 つのジョイントを持つ脚に TwoBoneIK Chain ソルバをアタッチしても構いません。また、LOD の方法を実装するために、チェーンの計算時間を実行中に変更することもできます。チェーンのソルバ タイプを確定的に定義する必要はありません。

次の図は、サンプルのクリーチャーに対して選択されているチェーンのソルバ タイプを示しています。

現在は、クリーチャー ソルバに実装されているチェーンには 5 つのタイプがあります。

チェーン 説明 パラメータ
HIKChainSolvingTypeOneBoneIK これは最も基本的なチェーンです。含まれているジョイントは 2 つのみで、1 つはチェーンの始点に、もう 1 つはチェーンの終点にあります。エフェクタ ReachT の値がゼロ以外の場合(位置コンストレイント)、ソルバはチェーンの始点のジョイントの方向を変え、終点エフェクタの位置を向くようにします。エフェクタ ReachR の値がゼロ以外の場合(方向コンストレイント)、終点ジョイントは指定したターゲットの方向に向きを変えます。 このソルバ モードは、CPU 使用率という点では非常に効果的です。たとえば、このモードをハチの腹部に使用することができます。 なし
HIKChainSolvingTypeTwoBonesIK これは 2 ボーンの IK ソルバです。始点ジョイント、中央ジョイント、終点ジョイントの 3 つのジョイントが含まれています。エフェクタ ReachT の値がゼロ以外の場合(位置コンストレイント)、チェーンを折り曲げたり伸ばしたりしてターゲット位置に到達できるように、始点ノードと中央ノードの方向が変わります。中央ジョイントの折り曲げ軸は、入力 FK 角度によって定義されます(または、この角度がフラットまたはゼロの場合は、「キャラクタライゼーションの自然なポーズ」によって)。エフェクタ ReachR の値がゼロ以外の場合(方向コンストレイント)、終点ノードのみが指定したターゲットの方向に向きを変えます。このソルバ モードは、CPU 使用率という点では非常に効果的です。たとえば、バッタの触覚に使用することができます。 HIKParamTwoBonesIK_FoldingJointIndex: キャラクタライゼーション時に宣言されたジョイント チェーン内の折り曲げジョイント(中間ジョイント)のゼロ ベースのインデックス。デフォルト値は 20 です。
HIKChainSolvingTypeCoplanar このソルバは、任意の長さのチェーンを計算することができます。これは同一平面上の付属器官(同一平面上のすべての折り曲げジョイント)でうまく動作しますが、同一平面にないチェーンに使用することもできます。このタイプのチェーンには、自由度(DOF)を指定することはできません。特定の内部ヒューリスティックにより、チェーンの異なるジョイント間に動きが伝播されます。始点ノードには高い自由度を割り付けられます(肩と同様であると考慮されます)。その他のノードは、入力 FK 角度によって定義された軸で折り曲げたり伸ばしたりすることができます(または、この角度がフラットまたはゼロの場合は、「キャラクタライゼーションの自然なポーズ」によって)。このソルバに対する CPU の消費量は、チェーンの長さ(リニア リレーションシップ)によって異なります。たとえば、クモの脚に使用することができます。 なし
HIKChainSolvingTypeTentacleApprox これは近似ソルバです。コンストレイントを正確に到達しませんが、入力 FK が IK ソリューションと近い位置にあるような簡単なソルバ設定では効率的です。このソルバは、任意の長さのチェーンを計算することができます。同一平面上のソルバとは異なり、これはターゲットに到達するためにどの軸でもジョイントを折り曲げることができます。方向コンストレイント(ReachR の値がゼロ以外の場合)の計算はチェーンのすべてのジョイントに分散されません。 終点ジョイントに直接設定されます。このソルバに対する CPU の消費量は、チェーンの長さ(リニア リレーションシップ)によって異なります。たとえば、トカゲの尻尾に使用することができます。 なし
HIKChainSolvingTypeTentacleCCD これは「背骨」または「首」のソルバと考えることができます。任意の長さのチェーンを計算することができます。ターゲット位置とターゲット方向の計算はチェーン内のすべての宣言済みジョイント全体に分散され、スムーズで連続した計算が行われます。ジョイントはいずれの方向にも折り曲げることができ、曲率を緩和するために、均一な角度制限を指定できます。このソルバは反復的であり(反復数を定義可能)、チェーンの長さに極度に依存するため、CPU の消費率が高いです。たとえば、ヘビの頭や首に使用することができます。
  • HIKParamTentacleCCD_IterationCount: ソルバの反復数。デフォルト値は 32 です。
  • HIKParamTentacleCCD_DOFAngle: 1 回の反復における 2 つの連続するジョイント間の折り曲げ角度の最大値。デフォルト値は 0.157 rad です。
  • HIKParamTentacleCCD_DOFMode: DOFAngle がチェーンに沿って分散する方法を定義します。さまざまな効果を実現するのに役立ちます。デフォルト値は DOFFunction_Linear です。
  • HIKParamTentacleCCD_EndOrientationInfluence: チェーンの開始点からの方向コンストレイント(ReachR の値)を考慮すべき場所を指定します。デフォルト値は 0.5f (50%)です。
HIKChainSolvingTypeQuadrupedLeg 四肢動物の脚を可変のジョイント数でアニメートする場合に、このチェーン タイプを使用します。おおむね HIKChainSolvingTypeCoplanar のように動作しますが、各ジョイントに対する個別のジョイント制限や、チェーンを構成するジョイントに対する計算順序を指定することができます。これにより、チェーン ジョイント間でチェーンのターゲット位置に不均等に到達するように動きが分配されます。 このチェーンのパラメータ数は、チェーンのジョイント構成の数と等しくなります。これらのパラメータにより、チェーンの計算順序が指定されます。これらはすべてチェーンのインデックス(0 ベース)を表します。最初のパラメータは修正する最初のジョイントを示し、2 番目のパラメータは修正する 2 番目のジョイントを示し、以降、同様に続きます。ジョイントの修正が早期であるほど、IK の問題の解決により貢献します。

手順 3: コードに移動する

  1. クリーチャーの定義を使用してソルバを初期化します。 以下に示すコードは、トカゲを動作させる場合の例です(上記のセクションの図を参照)。
    #define NB_LIZARD_CHAINS 5			// 4 legs and 1 tail
    
    HIKCreatureDefinition lDefinition;
    memset(&lDefinition, 0, sizeof(HIKCreatureDefinition));
    HIKCreatureChainDefinition * lChainDefinitions = new HIKCreatureChainDefinition[NB_LIZARD_CHAINS];	
    lDefinition.mNbChains = NB_LIZARD_CHAINS;
    lDefinition.mChains = lChainDefinitions;
    lDefinition.mHasParentOffset = false;
    lDefinition.mHasLimits = false;
    
    HIKCreatureSectionDefinition * lSectionDefinitions = NULL;
    lSectionDefinitions = new HIKCreatureSectionDefinition[1];
    lDefinition.mNbSections = 1;
    lDefinition.mSections = lSectionDefinitions;
    
  2. それぞれの計算チェーンに対してジョイントの数を設定します。スケルトンのジョイントをすべて宣言する必要はありません。IK ソルバに必要なジョイントを宣言すれば、その他のスケルトン ジョイントはスキップして構いません。
    for(int i=0; i<NB_LIZARD_CHAINS; i++)
    {
       switch(i)
       {
          case LIZARD_CHAIN_FRONT_LEG_L :
          case LIZARD_CHAIN_FRONT_LEG_R :
             lChainDefinitions[i].mNbNodes = 4;	  // 4 joints for the back legs
             break;
          case LIZARD_CHAIN_BACK_LEG_L :
          case LIZARD_CHAIN_BACK_LEG_R :
             lChainDefinitions[i].mNbNodes = 3;	  // 3 joints for the back legs
             break;
          default:
             lChainDefinitions[i].mNbNodes = 6;	  // 6 joints for the tail
             break;
        }			
        lChainDefinitions[i].mSection = 0;       // All Chains are attached to Section 0
        lChainDefinitions[i].mNbParentOffsets = 0;
        lChainDefinitions[i].mNbLimits = 0;
    }
    
  3. セクションの定義を設定します。これが終わったら、この定義から HIKCreature オブジェクトを作成するために HumanIK の API 関数を呼び出します。評価版をお使いの場合、次の関数に対し、お使いのライセンス文字列をコピーして最後のパラメータとして使用してください。
    lSectionDefinitions[0].mParentChain = -1;
    
    mHIKCreature = HIKCreatureCreate(&lDefinition, &malloc, "LicenseHere!!!");
    if(mHIKCreature == NULL)
       return false;
    

    コードをさらに記述する前に、Verbose ビルドに対して構築されたアプリケーションを使って、ここまでのコードの実行を試す必要があります。これにより、エラーをモニタするためのログ ファイル (humaniklog.txt) が生成されます。クリーチャー ソルバはキャラクタ ソルバよりもはるかに詳細なレポートを出力します。

  4. クリーチャー キャラクタライゼーションのポーズを HumanIK に指定します。宣言済みチェーン ジョイントのそれぞれと宣言済みセクションのそれぞれに対し、デフォルト位置、デフォルト方向、デフォルト スケールを指定したソルバを与える必要があります。これらの変換はクリーチャーの「自然なポーズ」から作成する必要があります。「自然なポーズ」は「T スタンス」ではなく(T スタンスは自然に見えません)、すべての手足が明示的な角度で折り曲げられている一般的なポーズです(角度がフラットまたはゼロではなく、完全に伸ばしきった状態でもない)。
    HIKCreatureSetCharacterizeNodeStateTQSfv(
        mHIKCreature,
        lLizardProfile->mBoneMapping[i].mChainID,
        lLizardProfile->mBoneMapping[i].mBoneID,
        jointTranslation, jointOrientation, jointScale);
    
    注: この関数呼び出しの 2 番目のパラメータは、チェーン変換の設定時は正の値で、セクション変換の設定時は負の値です。クリーチャー定義内のチェーンとセクションの宣言順序により、ID が定義されます(配列内の単純なインデックス)。3 番目のパラメータには、チェーンを扱う場合はゼロでない値のみを設定します。これにより、設定することが必須であるチェーンの始点からのジョイント インデックスが定義されます。
    注:クリーチャーが親のオフセットまたはジョイントの制限を実装した場合(上記の手順 1 と 2 で設定したセクションとチェーンの定義に事前宣言された通り)、実際にはどのノードが親のオフセットやジョイントの制限を実装するのかを示す必要があります。これはチェーン ノードに対してのみ必要で、セクション ノードには必要ありません。特定のノードが親のオフセットを実装した場合、そのノードに対して HIKCreatureSetHasParentOffset 関数を呼び出してタグ付けされるようにする必要があります。特定のノードがジョイントの制限を実装した場合、そのノードに対して HIKCreatureSetHasLimits 関数を呼び出してタグ付けされるようにする必要があります。
  5. HIKCreatureCharacterizeGeometry 関数を呼び出して、作成したキャラクタライゼーションを検証します。
    bool result = HIKCreatureCharacterizeGeometry(mHIKCreature);
    if(res == false)
    {
           // Something is wrong. Check your log.
    }
    
  6. 初期化シーケンスを完成させるために、「チェーンの固さ」などのその他のパラメータとともに、初期チェーンのソルバ タイプを設定します。
    // Set Chain types
    
    HIKCreatureSetChainSolvingType(mHIKCreature, LIZARD_CHAIN_TAIL, HIKChainSolvingTypeTentacleApprox);
    HIKCreatureSetChainSolvingType(mHIKCreature, LIZARD_CHAIN_FRONT_LEG_L, HIKChainSolvingTypeCoplanar);
    HIKCreatureSetChainSolvingType(mHIKCreature, LIZARD_CHAIN_FRONT_LEG_R, HIKChainSolvingTypeCoplanar);
    HIKCreatureSetChainSolvingType(mHIKCreature, LIZARD_CHAIN_BACK_LEG_L, HIKChainSolvingTypeCoplanar);
    HIKCreatureSetChainSolvingType(mHIKCreature, LIZARD_CHAIN_BACK_LEG_R, HIKChainSolvingTypeCoplanar);
    
    // Add stiffness to front leg chains
    
    HIKCreatureSetChainStiffness(mHIKCreature, LIZARD_CHAIN_FRONT_LEG_L, 0.75f);
    HIKCreatureSetChainStiffness(mHIKCreature, LIZARD_CHAIN_FRONT_LEG_R, 0.75f);
    	
    // No stiffness at all for the tail
    
    HIKCreatureSetChainStiffness(mHIKCreature, LIZARD_CHAIN_TAIL, 0.0f);
    

    ソルバに FullBodyIK の pull と torque を計算させるかどうかを指定することができます。 これらの機能を有効にすると結果を向上させることができますが、CPU の負担が増えます。次の関数を使うことにより、pull と torque の計算をいつでも有効化/無効化できます(たとえば、クリーチャーがカメラに近づいたときにだけ有効にすることができます)。

    // Enable both pull and torque
    
    HIKCreatureEnableFBIK(mHIKEffectorSetState, true);
    HIKCreatureEnableTorque(mHIKEffectorSetState, true);
    

  7. 上記の手順(手順 1、2、および 4)でノードの制限を事前に宣言していた場合、ここで HIKCreatureSetLimitsfv 関数を呼び出すことによって関連ノードに対する実際の制限を定義することができます。クリーチャー ソルバの制限はキャラクタ ソルバと同様に動作します。
  8. ログ ファイル (humaniklog.txt)をチェックします。キャラクタライゼーションのプロセス中に無効な変換が発生した場合、HumanIK はこのファイルに警告またはエラーを書き込みます。