アニメーション X-FILE を作成する

Animation X-FILE を Text Editor で作成します。
Java で X-FILE を描画するプログラムを作成しています。
前田稔の超初心者のプログラム入門 から
「Java 3D 入門/Loader の作成/X-FILE Loader」を参照して下さい。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. Animation X-FILE は、専用の3Dモデルツールを使って作成するのが一般的なのですが、ファイルの形式を理解するために Text Editor を使ってシンプルな X-FILE を作成してみましょう。
    X-FILE は template と呼ばれる構造体のような記述に従って作成されています。
    template のソースを広げて、比較しながら読んで下さい。
  2. 最初の一行はファイルのIDです。
    「xof」が X-FILE の識別で、次の「03」はメジャーバージョン、次の「03」はマイナーバージョンです。
    「txt」はテキストファイルであることを示し、バイナリモードでは「bin」となります。
    最後の「0032」は、数字を 32bit で読み込むことを宣言しています。
    xof 0303txt 0032
  3. X-FILE の Header です。
    最初の「1」がメジャーバージョン、次の「0」はマイナーバージョン、次の「1」はフラグです。
    Header {
     1;
     0;
     1;
    }
    
  4. Frame でポリゴンメッシュの階層構造を定義します。
    Frame の名前(Anim_MatrixFrame_Box)などは SkinWeights と Animation から参照されます。
    Frame には、大抵 FrameTransformMatrix が書かれているのですが、その役割が不明 (?_?; で 値を変更しても影響がありません。
    極端な話、削除しても動くようで、Anim_MatrixFrame_Box 以外からは削除してしまいました。 (^_^;)
    Frame Frame_Root
    {
      Frame Anim_MatrixFrame_Subroot
      {
        Frame Anim_MatrixFrame_Box
        { FrameTransformMatrix
          {
            1.000000, 0.0, 0.0, 0.0, 
            0.0, 1.000000, 0.0, 0.0, 
            0.0, 0.0, 1.000000, 0.0, 
            0.0, 0.0, 0.0, 1.000000;;
          }
    
  5. Box Mesh の定義です。
    ツールで作成した場合は、全てのパーツ(今回の場合は Box と Cone)をまとめて記述しているようですが、 わかり易さを考えて親(Box)と子(Cone)に分けて定義してみました。
    極力シンプルになるように、頂点座標と法線ベクトルでモデルを作成しています。
    Box は立方体のモデルで、8個の頂点を持っています。
    立方体の6個の面を12個の三角形ポリゴンで構成します。
    ツールを使うと、ここまでシンプルには行かないのですが、さすがに Text Edit で作成すると思いのままです。 (^_^;)
    メッシュの説明は メッシュを生成して X-FILE に保存する 参照して下さい。
          Mesh
          {
            //Vertex
            8;
            -0.5;0.5;0.5;,
            -0.5;0.5;-0.5;,
            0.5;0.5;0.5;,
            0.5;0.5;-0.5;,
            0.5;-0.5;0.5;,
            0.5;-0.5;-0.5;,
            -0.5;-0.5;0.5;,
            -0.5;-0.5;-0.5;;
    
            //Index
            12;
            3;1,0,2;,
            3;2,3,1;,
            3;3,2,4;,
            3;4,5,3;,
            3;2,0,6;,
            3;6,4,2;,
            3;0,1,7;,
            3;7,6,0;,
            3;1,3,5;,
            3;5,7,1;,
            3;7,5,4;,
            3;4,6,7;;
    
            MeshNormals
            {
              8;
              -0.577350;0.577350;0.577350;,
              -0.577350;0.577350;-0.577350;,
              0.577350;0.577350;0.577350;,
              0.577350;0.577350;-0.577350;,
              0.577350;-0.577350;0.577350;,
              0.577350;-0.577350;-0.577350;,
              -0.577350;-0.577350;0.577350;,
              -0.577350;-0.577350;-0.577350;;
    
              //Box Normal Index
              12;
              3;1,0,2;,
              3;2,3,1;,
              3;3,2,4;,
              3;4,5,3;,
              3;2,0,6;,
              3;6,4,2;,
              3;0,1,7;,
              3;7,6,0;,
              3;1,3,5;,
              3;5,7,1;,
              3;7,5,4;,
              3;4,6,7;;
            } // End of MeshNormals
    
  6. 続いて XSkinMeshHeader と SkinWeights で、ボーンを定義します。
    nBones は、ここで定義しているボーンの数です。
    "Anim_MatrixFrame_Box" は Frame の名前です。
    「8」は影響を受ける頂点の数で、0 ~ 7 はその Index 番号です。
    次の8個の 1.000000 は、Index で示された頂点への影響の強さで、数値が小さくなるほど影響しなくなります。
    次に4*4の変換行列を指定します。
    Frame の FrameTransformMatrix と違って、こちらは効果覿面です。 (^_^;)
    今回は Box と Cone が重ならないように Box のY座標をずらしています。
    変換行列の説明は 変換行列を使って Light を回転する 参照して下さい。
            XSkinMeshHeader
            {
              4; // nMaxSkinWeightsPerVertex
              3; // nMaxSkinWeightsPerFace
              1; // nBones
            }  // End of XSkinMeshHeader
    
            SkinWeights
            {
              "Anim_MatrixFrame_Box";
              8; // nWeights  Box
              0,1,2,3,4,5,6,7;;
              1.000000,1.000000,1.000000,1.000000,1.000000,
              1.000000,1.000000,1.000000;;
              1.000000, 0.0, 0.0, 0.0, 
              0.0, 1.000000, 0.0, 0.0, 
              0.0, 0.0, 1.000000, 0.0, 
              0.0, -1.65, 0.0, 1.000000;;
            }  // End of SkinWeights
          } // End of Mesh
    
  7. 続いて Anim_MatrixFrame_Cone の Frame と Mesh の定義です。
    ソースコードが長くならないように Cone は8角形で構成しています。
    最初の8個が Cone の筒の部分で、後の8個が蓋の部分です。
    説明は Box に準じます。
          Frame Anim_MatrixFrame_Cone
          {
            Mesh
            {
              10;
              1.054129;-1.133686;0.000000;,
              0.739557;-1.133686;0.759446;,
              -0.019889;-1.133686;1.074019;,
              -0.779335;-1.133686;0.759446;,
              -1.093908;-1.133686;0.000000;,
              -0.779335;-1.133686;-0.759446;,
              -0.019889;-1.133686;-1.074019;,
              0.739557;-1.133686;-0.759446;,
              -0.019889;1.093908;0.000000;,
              0.000000;-1.133686;0.000000;,
    
              //Index
              16;
              3;8,1,0;,
              3;8,2,1;,
              3;8,3,2;,
              3;8,4,3;,
              3;8,5,4;,
              3;8,6,5;,
              3;8,7,6;,
              3;8,0,7;,
     
              3;9,0,1;,
              3;9,1,2;,
              3;9,2,3;,
              3;9,3,4;,
              3;9,4,5;,
              3;9,5,6;,
              3;9,6,7;,
              3;9,7,0;,
    
              MeshNormals
              {
                10;
                0.894501;0.431277;0.117763;,
                0.549236;0.431277;0.715779;,
                -0.117763;0.431277;0.894501;,
                -0.715779;0.431277;0.549236;,
                -0.894501;0.431277;-0.117763;,
                -0.549236;0.431277;-0.715779;,
                0.117763;0.431277;-0.894501;,
                0.715779;0.431277;-0.549236;,
                0.000000;-1.000000;0.000000;,
                0.000000;1.000000;0.000000;,
    
                16;
                3;8,1,0;,
                3;8,2,1;,
                3;8,3,2;,
                3;8,4,3;,
                3;8,5,4;,
                3;8,6,5;,
                3;8,7,6;,
                3;8,0,7;,
     
                3;9,0,1;,
                3;9,1,2;,
                3;9,2,3;,
                3;9,3,4;,
                3;9,4,5;,
                3;9,5,6;,
                3;9,6,7;,
                3;9,7,0;,
              } // End of MeshNormals
    
              XSkinMeshHeader
              {
                4; // nMaxSkinWeightsPerVertex
                3; // nMaxSkinWeightsPerFace
                1; // nBones
              }  // End of XSkinMeshHeader
    
              SkinWeights
              {
                "Anim_MatrixFrame_Cone";
                10; // nWeights  Cone
                0,1,2,3,4,5,6,7,8,9;;
                1.000000,1.000000,1.000000,1.000000,1.000000,
                1.000000,1.000000,1.000000,1.000000,1.000000;;
                1.000000, 0.0, 0.0, 0.0, 
                0.0, 1.000000, 0.0, 0.0, 
                0.0, 0.0, 1.000000, 0.0, 
                0.0, 0.0, 0.0, 1.000000;;
              } // End of SkinWeights
            } // End of Mesh
          }  // End of SkinWeights
        } // End animation 'Box' frame
      } // End of 'Subroot' animation matrix frame
    } // End of "Frame_Root" frame
    
    ここまでで、モデルの定義は一応完了で、ダブルクリックで起動すると Box と Cone が描画されます。
  8. いよいよアニメーションの設定です。
    X-FILE 上でアニメーションの記述は Mesh とは独立しているようで、X-FILE の後に追加するような形になっています。
    {Anim_MatrixFrame_Cone} の名前で Animation と Frame と SkinWeights を関連づけます。
    AnimationKey でボーンの動きを設定します。
    「0」は Rotation(回転)で、32 個のアニメーションデータを設定しています。
    各データの最初の「180;」などはタイマ(時刻)の指定です。
    タイマ間隔が荒くなっても、その間を補完してアニメーションしてくれるので、スムースな動きになります。
    つぎの「4;0.963718,0.042017,0.259454,0.046533;;」が回転情報です。
    回転情報は回転軸と回転角度を指示するクォータニオン(Quaternion)(日本語で 4元数)で設定します。
    私はツールで作成した X-FILE から利用できそうな値をコピーして修正しました。
    AnimationSet AnimationSet0
    {
      Animation Animation0
      {
        {Anim_MatrixFrame_Cone}
        AnimationKey
        {
          0;  // Rotation
          32;          
          0;4;1.0,0.0,0.0,0.0;;,
          180;4;0.963718,0.042017,0.259454,0.046533;;
          360;4;0.886548,-0.185896,0.390418,0.164468;;
          540;4;0.837173,-0.171193,0.505718,0.118670;;
          720;4;0.775773,-0.128750,0.614057,0.067331;;
          900;4;0.708949,-0.017941,0.704968,-0.009424;;
          1080;4;0.588805,0.153571,0.783233,-0.127560;;
          1260;4;0.524820,0.224055,0.792288,-0.215970;;
          1440;4;0.475905,0.259014,0.798333,-0.262849;;
          1620;4;0.429517,0.291690,0.811758,-0.267360;;
          1800;4;0.379385,0.322856,0.825892,-0.264069;;
          1980;4;0.300265,0.376852,0.833764,-0.269558;;
          2160;4;0.218214,0.426414,0.835673,-0.268708;;
          2340;4;0.175710,0.453822,0.834758,-0.257586;;
          2520;4;0.181934,0.433645,0.866780,-0.165966;;
          2700;4;0.203223,0.228321,0.949051,0.076635;;
          2880;4;0.192525,0.037311,0.923752,0.328975;;
          3060;4;0.200877,-0.077330,0.939491,0.266507;;
          3240;4;0.204054,-0.187964,0.949597,0.145937;;
          3420;4;0.198645,-0.301039,0.932523,0.017782;;
          3600;4;0.182918,-0.357978,0.913235,-0.066293;;
          3780;4;0.153978,-0.263317,0.952073,-0.022620;;
          3960;4;0.122664,-0.168357,0.977948,0.015089;;
          4140;4;0.088345,-0.072389,0.992284,0.048241;;
          4320;4;0.066657,0.015581,0.997635,-0.006211;;
          4500;4;0.064417,-0.060107,0.993222,0.075809;;
          4680;4;0.059568,-0.061032,0.994514,0.060564;;
          4860;4;0.050967,-0.027529,0.998143,0.018829;;
          5040;4;0.045838,-0.019511,0.998748,0.004581;;
          5220;4;0.043670,-0.022703,0.998788,0.000213;;
          5400;4;0.040984,0.016468,0.999023,0.001059;;
          5820;4;0.038249,0.002162,0.999266,0.000730;;
          8700;4;0.038249,0.002162,0.999266,0.000730;;
        }
    
  9. Position(移動)の AnimationKey です。
    「2」が Position で、32 個のデータを設定しています。
    keyType は次のようになります。
    各データの最初の「180;」などはタイマ(時刻)の指定です。
    つぎの「3;0.046937,1.892451,0.000000;;,」が X,Y,Z の移動情報です。
        AnimationKey
        {
          2;  // Position
          32;
          0;3;0.000000,1.108158,0.000000;;,
          180;3;0.046937,1.892451,0.000000;;,
          360;3;0.093805,2.339689,0.000000;;,
          540;3;0.140533,2.673684,0.000000;;,
          720;3;0.187052,2.895210,0.000000;;,
          900;3;0.233291,3.000247,0.000000;;,
          1080;3;0.279182,2.994432,0.000000;;,
          1260;3;0.324653,2.884793,0.000000;;,
          1440;3;0.369637,2.676282,0.000000;;,
          1620;3;0.405806,2.426638,0.000000;;,
          1860;3;0.457956,1.973661,0.000000;;,
          2040;3;0.503370,1.551488,0.000000;;,
          2220;3;0.549449,1.025496,0.000000;;,
          2400;3;0.595880,0.387643,0.000000;;,
          2580;3;0.652755,0.133335,0.000000;;,
          2820;3;0.692545,0.342768,0.000000;;,
          3000;3;0.621517,0.430906,0.000000;;,
          3180;3;0.550312,0.447761,0.000000;;,
          3360;3;0.478799,0.393138,0.000000;;,
          3540;3;0.401974,0.382679,0.000000;;,
          3720;3;0.320851,0.377154,0.000000;;,
          3900;3;0.245339,0.353590,0.000000;;,
          4260;3;0.1609594,0.276867,0.000000;;,
          4440;3;0.145729,0.175066,0.000000;;,
          4620;3;0.077017,0.051254,0.000000;;,
          4800;3;0.074381,0.131492,0.000000;;,
          5040;3;0.071948,0.149115,0.000000;;,
          5220;3;0.071372,0.104626,0.000000;;,
          5400;3;0.001955,0.038438,0.000000;;,
          5580;3;0.001055,0.074264,0.000000;;,
          5760;3;0.000254,0.054173,0.000000;;,
          6000;3;0.000000,0.053507,0.000000;;,
        }
      }
    }
    
  10. 説明したソースコードをつなげて X-FILE を作成して下さい。
    ダブルクリックで起動すると、Box の上に Cone が落下するアニメーションが描画されます。

超初心者のプログラム入門(DirectX9 game program)

超初心者のプログラム入門(DirectX10 game program)