2012年8月30日 星期四

自訂變形節點

UE的動畫樹(AnimTree)提供動畫混合、變形混合、骨架控制三種功能。它可以讓開發者自訂節點來擴充新的功能,在此篇簡單說明一下如何自訂變形節點。

變形節點的基礎類別叫做MorphNodeBase,其他的變形節點都會直接或間接繼承自此類別。它定義數個C++虛擬函式以供子類別擴充,以下列出重要的成員:
  • NodeName [name] :使用者可自行定義的節點名稱。可以呼叫SkeletalMeshComponent的FindMorphNode()函式找到指名的變形節點。
  • InitMorphNode(SkeletalMeshComponent) :動畫樹會呼叫此函式初始化變形節點。
  • GetNodes(TArray<UMorphNodeBase*>& OutNodes):列出此節點和其下所有節點。
  • GetActiveMorphs(TArray<FActiveMorph>& OutMorphs):列出以此節點算起子樹的所有節點裡,作用中的變形目標和其權重。

每個SkeletalMeshComponent會複製一份專用的動畫樹,所以即使許多模型使用同一個動畫樹範本,像是變形節點權重這種每個實例都要另記一份的資料,還是可以直接存放在變形節點上。大部分變形節點的功能是由C++實作,所以沒有原始碼授權的UDK使用者很難去擴充節點。

範例


以下程式碼展示如何自訂一個會隨生命值減少增加權重的變形節點:
class MyMorphNodeWeightByHealth extends MorphNodeWeightBase
    native(Anim);
    
cpptext
{
    // MorphNodeBase interface
    virtual void GetActiveMorphs( TArray<FActiveMorph>& OutMorphs );
}

defaultproperties
{
    NodeConns(0)=(ConnName=In)
}
先利用生命值計算目前權重,然後乘進子樹裡:
void UMyMorphNodeWeightByHealth::GetActiveMorphs( TArray<FActiveMorph>& OutMorphs )
{
    FLOAT NodeWeight = 0.f;
    
    // The weight is the ratio of current health to max health.
    if( SkelComponent )
    {
        APawn* Pawn = Cast<APawn>( SkelComponent->GetOwner() );
        if( Pawn && Pawn->HealthMax > KINDA_SMALL_NUMBER )
        {
            NodeWeight = Clamp( FLOAT(Pawn->HealthMax - Pawn->Health) / Pawn->HealthMax, 0.f, 1.f );
        }
    }
    
    check( NodeConns.Num() == 1 );
    FMorphNodeConn& Conn = NodeConns(0);
    
    TArray<FActiveMorph> Morphs;
    for(INT i=0; i<Conn.ChildNodes.Num(); i++)
    {
        if( Conn.ChildNodes(i) )
        {
            Morphs.Empty();
            Conn.ChildNodes(i)->GetActiveMorphs(Morphs);
            
            for(INT j=0; j<Morphs.Num(); j++)
            {
                OutMorphs.AddItem(FActiveMorph( Morphs(j).Target, Morphs(j).Weight * NodeWeight ));
            }
        }
    }
}

沒有留言:

張貼留言