﻿/******************************************************************************
    DccAnimation の使用方法

    Date: 2015/04/02

    Copyright (C)Nintendo All rights reserved.
******************************************************************************/

// 改訂履歴

/******************************************************************************
    概要
******************************************************************************/

//-----------------------------------------------------------------------------
// DccAnimation
DccAnimation はアニメーション関連のライブラリです。
ベイクしたデータからアニメーションカーブを作成する処理などが含まれます。

//-----------------------------------------------------------------------------
// フレームの定義
DCC ツール上と同じ単位のフレームを「浮動小数点数フレーム」、
Export オプションの Frame Precision 単位で
何フレームかをあらわした整数を「整数サブフレーム」と呼びます。

// Frame Precision が 1.0 の場合
整数サブフレームと浮動小数点数フレームは同じです。

// Frame Precision が 0.5 の場合
整数サブフレーム    : 0    1    2    3    4    5    ...
浮動小数点数フレーム: 0.0  0.5  1.0  1.5  2.0  2.5  ...

// Frame Precision が 0.2 の場合
整数サブフレーム    : 0    1    2    3    4    5    ...
浮動小数点数フレーム: 0.0  0.2  0.4  0.6  0.8  1.0  ...

// Frame Precision が 0.1 の場合
整数サブフレーム    : 0    1    2    3    4    5    ...
浮動小数点数フレーム: 0.0  0.1  0.2  0.3  0.4  0.5  ...

DCC ツールによっては、ちょうど 0.1 や 0.2 フレーム単位でベイクできない場合があります。
その場合は 0.1 や 0.2 フレーム単位に近いフレームでベイクします。

例えば、Maya の 時間の最小単位は 1/6000 sec であり、
作業単位の時間が 240 frame/sec なら、
フレームの最小単位は 1/(6000 / 240) = 1/25 = 0.04 なので、
Frame Precision が 0.1 なら次のようになります。

// Maya で 240 frame/sec かつ Frame Precision が 0.1 の場合
整数サブフレーム    : 0    1     2     3     4     5     ...
浮動小数点数フレーム: 0.0  0.08  0.20  0.32  0.40  0.48  ...

/******************************************************************************
    【手順 1】 ヘッダを include
******************************************************************************/

#include "DccAnimation.h"
using namespace nn::gfx::tool::dcc;

/******************************************************************************
    【手順 2】 整数サブフレームから浮動小数点数フレームを取得する関数を定義
******************************************************************************/

extern float GetFloatFrameFromSubFrame(const int subFrame, const void* pParam)
{
    // この例では第 2 引数で RExpOpt オブジェクトのポインタを受け取ります。
    const RExpOpt& opt = *reinterpret_cast<const RExpOpt*>(pParam);
    return static_cast<float>(subFrame) / opt.m_FramePrecision;
    // ちょうど 0.1 や 0.2 フレーム単位でベイクしていない場合は
    // m_FramePrecision で割るだけでなく補正が必要です。
}

/******************************************************************************
    【手順 3】 ベイクしたデータを取得
******************************************************************************/

アニメーションする各パラメータについて、
DCC ツールからベイクしたデータ（全サブフレームにおける値の配列）を取得して、
RFloatArray 型の変数に格納します。

/******************************************************************************
    【手順 4】 回転値が連続的になるように補正
******************************************************************************/

// ボーンの場合は次の関数で 3 軸同時に補正します。
RMakeContinuousXyzAngleArray(
    (X 回転をベイクしたデータ),
    (Y 回転をベイクしたデータ),
    (Z 回転をベイクしたデータ)
);

// カメラの場合は次の関数で 3 軸同時に補正します。
// 【現在カメラのアニメーションは出力しません】
RMakeContinuousZxyAngleArray(
    (X 回転をベイクしたデータ),
    (Y 回転をベイクしたデータ),
    (Z 回転をベイクしたデータ)
);

// それ以外の回転値（テクスチャ SRT の回転）に関しては
// アニメーションカーブ作成時に補正するので
// この段階での補正は不要です。

/******************************************************************************
    【手順 5】 RAnimCurve オブジェクトを生成
******************************************************************************/

RAnimCurve curve;
curve.m_LoopFlag   = (ループアニメーションなら true);
curve.m_AngleFlag  = (角度のアニメーションなら true);
curve.m_Tolerance  = (Export オプションで指定された誤差の許容値);
curve.m_PreWrap    = (最初のキーより前のフレームにおける評価モード);
curve.m_PostWrap   = (最後のキーより後のフレームにおける評価モード);
curve.m_FullValues = (ベイクしたデータ);

// 一定フラグ（m_ConstantFlag）を更新します。
curve.UpdateConstantFlag();

/******************************************************************************
    【手順 5】ベイクしたデータからアニメーションカーブを作成
******************************************************************************/

//-----------------------------------------------------------------------------
// スケルタルアニメーション、カラーアニメーション、テクスチャ SRT アニメーションでは、
// エルミート補間用のアニメーションキー配列を作成します。
if (!curve.m_ConstantFlag)
{
    curve.MakeKeys(GetFloatFrameFromSubFrame, &opt, continuousAngleFlag);
}

continuousAngleFlag は、
スケルタルアニメーションは手順 4 で補正済みなので false、
それ以外のアニメーションは true を指定します。

//-----------------------------------------------------------------------------
// ボーンビジビリティアニメーション、テクスチャパターンアニメーションでは、
// ステップ補間用のアニメーションキー配列を作成します。
if (!curve.m_ConstantFlag)
{
    curve.MakeStepKeys(GetFloatFrameFromSubFrame, &opt);
}

/******************************************************************************
    【手順 6】出力
******************************************************************************/

// RInitOutStreamFormat で出力ストリーム os の書式を設定しておきます。

//-----------------------------------------------------------------------------
// スケルタルアニメーション、カラーアニメーション、テクスチャ SRT アニメーションでは、
// 次の関数でアニメーションターゲット要素を出力します。
curve.Out(os, (データ列配列), (インデントに必要なタブ数),
    (アニメーションターゲット要素名), (target 属性の値), isOriginal);

isOriginal は、
スケルタルアニメーションは false、
それ以外のアニメーションは true を指定します。

//-----------------------------------------------------------------------------
// ボーンビジビリティアニメーション、テクスチャパターンアニメーションでは、
// 次の関数でアニメーションカーブ要素を出力します。
curve.Out(os, (データ列配列), (インデントに必要なタブ数), false);

//-----------------------------------------------------------------------------
// データ列配列は中間ファイルの最後にまとめて出力します。
// 手順は FDC_Shape_Usage.cpp と同様です。

/******************************************************************************
    改訂履歴
******************************************************************************/

■ 2013/06/26
RAnimCurve::Wrap に RELATIVE_REPEAT を追加。

■ 2012/02/21
定数を大文字に変更。

■ 2011/05/12
初版。

