.Xのスキンメッシュアニメーションを読み込んでみる2

「.Xのスキンメッシュアニメーションを読み込んでみる2」の編集履歴(バックアップ)一覧はこちら

.Xのスキンメッシュアニメーションを読み込んでみる2」(2014/04/20 (日) 11:36:22) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

<div> <div><strong>.x のスキンメッシュアニメーションを読み込んで表示します。</strong></div> <div><strong>このプログラムは <a href="http://www21.atwiki.jp/opengl?cmd=upload&amp;act=open&amp;pageid=235&amp;file=box.x">box.x</a> 専用です。</strong></div> <div><strong>わかりやすくするために敢えて、このようにしました。</strong></div> </div> <div> </div> <div><strong><img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&amp;act=open&amp;pageid=235&amp;file=skin.png" /><br /></strong></div> <div>  </div> <div><strong>これで完成ではありません。</strong></div> <div><strong>法線を再設定してあげないと光の反射具合が変になってしまいます。</strong></div> <div><strong>詳しくは次回に回します。</strong></div> <div> </div> <div>font.h</div> <table cellspacing="1" cellpadding="1" width="600" border="1"><tbody><tr><td> <div>#pragma once</div> <div>class GLFONT</div> <div>{</div> <div>public:</div> <div> HFONT Hfont;</div> <div> HDC Hdc;</div> <div> GLFONT(wchar_t *fontname, int size);</div> <div> void DrawStringW(int x,int y,wchar_t *format, ...);</div> <div>};</div> <div>//コンストラクタ フォント作成</div> <div>GLFONT::GLFONT(wchar_t *fontname, int size)</div> <div>{</div> <div> Hfont = CreateFontW(</div> <div>        size,      //フォント高さ</div> <div>        0,       //文字幅</div> <div>        0,       //テキストの角度</div> <div>        0,       //ベースラインとx軸との角度</div> <div>        FW_REGULAR,     //フォントの太さ</div> <div>        FALSE,      //イタリック体</div> <div>        FALSE,      //アンダーライン</div> <div>        FALSE,      //打ち消し線</div> <div>        SHIFTJIS_CHARSET,   //文字セット</div> <div>        OUT_DEFAULT_PRECIS,   //出力精度</div> <div>        CLIP_DEFAULT_PRECIS,  //クリッピング精度</div> <div>        ANTIALIASED_QUALITY,  //出力品質</div> <div>        FIXED_PITCH | FF_MODERN, //ピッチとファミリー</div> <div>        fontname);     //書体名</div> <div> </div> <div> Hdc = wglGetCurrentDC();</div> <div> SelectObject(Hdc, Hfont);</div> <div>}</div> <div>//ワイド文字列の描画</div> <div>void GLFONT::DrawStringW(int x,int y,wchar_t *format, ...)</div> <div>{</div> <div> wchar_t buf[256];</div> <div> va_list ap;</div> <div> int Length=0;</div> <div> int list=0;</div> <div> </div> <div> //ポインタがNULLの場合は終了</div> <div> if ( format == NULL )</div> <div>  return;</div> <div> </div> <div> //文字列変換</div> <div> va_start(ap, format);</div> <div> vswprintf_s(buf, format, ap);</div> <div> va_end(ap);</div> <div> </div> <div> Length = wcslen(buf);</div> <div> list = glGenLists(Length);</div> <div> for( int i=0; i&lt;Length; i++ ){</div> <div>  wglUseFontBitmapsW(Hdc, buf[i], 1, list + (DWORD)i);</div> <div> }</div> <div> </div> <div> glDisable(GL_LIGHTING);</div> <div> glRasterPos2i(x, y);</div> <div> //ディスプレイリストで描画</div> <div> for( int i=0; i&lt;Length; i++ )</div> <div> {</div> <div>  glCallList(list + i);</div> <div> }</div> <div> glEnable(GL_LIGHTING);</div> <div> //ディスプレイリスト破棄</div> <div> glDeleteLists(list, Length);</div> <div> list = 0;</div> <div> Length = 0;</div> <div>}</div> </td> </tr></tbody></table><div> </div> <div> </div> <div>PNG.h</div> <table cellspacing="1" cellpadding="1" width="600" border="1"><tbody><tr><td> <p>#pragma once<br /> #include "lodepng.h"</p> <p>//テクスチャクラス<br /> class TEXTURE{<br /> protected:<br />  LodePNG_Decoder decoder;//デコーダ<br />  unsigned char* buffer;//バッファ<br />  size_t buffersize, imagesize;//サイズ<br /> public:<br />  TEXTURE();<br />  TEXTURE(const char* FileName);//コンストラクタ<br />  void LOAD_PNG(const char* FileName);//PNG読み込み<br />  unsigned char* image;//イメージポインタ<br />  unsigned int Width,Height;//画像サイズ<br /> };<br /> TEXTURE::TEXTURE(){<br /> }<br /> TEXTURE::TEXTURE(const char* FileName){<br />  LOAD_PNG(FileName);<br /> }<br /> void TEXTURE::LOAD_PNG(const char* FileName){<br />  LodePNG_Decoder_init(&amp;decoder);<br />  //ロード<br />  LodePNG_loadFile(&amp;buffer, &amp;buffersize, FileName);<br />  //デコード<br />  LodePNG_decode(&amp;decoder, &amp;image, &amp;imagesize, buffer, buffersize);<br />  //幅,高さ<br />  Width = decoder.infoPng.width;Height = decoder.infoPng.height;<br /> }</p> </td> </tr></tbody></table><div> </div> <div>xfile.h</div> <table cellspacing="1" cellpadding="1" width="600" border="1"><tbody><tr><td> <p>#pragma once<br /> #include "PNG.h"<br /> #include &lt;math.h&gt;</p> <p>#define PAI 3.14159</p> <p>using namespace std;<br /> struct MATRIX;<br /> //クォータニオン構造体<br /> struct QUATERNION{<br />  union {<br />   struct {<br />    float w;<br />    float x;<br />    float y;<br />    float z;<br />   };<br />   float Index[4];<br />  };<br />  MATRIX ToMatrix();//クォータニオンを回転行列にする<br /> }qua;</p> <p>//マトリクス構造体<br /> struct MATRIX {<br />     union {<br />         struct {<br />             float _11, _12, _13, _14;<br />             float _21, _22, _23, _24;<br />             float _31, _32, _33, _34;<br />             float _41, _42, _43, _44;<br />         };<br />         float mat_4x4[4][4];<br />         float mat_16[16];<br />     };<br />  MATRIX(){//単位行列に初期化<br />   for(int i=0;i&lt;16;i++){<br />    this-&gt;mat_16[i]=0;<br />   }<br />   this-&gt;_11=this-&gt;_22=this-&gt;_33=this-&gt;_44=1;<br />  }<br />  void PRINT(char* text){<br />   printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />    text,<br />    this-&gt;_11,this-&gt;_21,this-&gt;_31,this-&gt;_41,<br />    this-&gt;_12,this-&gt;_22,this-&gt;_32,this-&gt;_42,<br />    this-&gt;_13,this-&gt;_23,this-&gt;_33,this-&gt;_43,<br />    this-&gt;_14,this-&gt;_24,this-&gt;_34,this-&gt;_44);<br />  }</p> <p> MATRIX Multiplication(MATRIX&amp; mat);//合成<br />  QUATERNION ToQuaternion();//回転行列をクォータニオンにする<br /> };<br /> //合成<br /> MATRIX MATRIX::Multiplication(MATRIX&amp; mat)<br /> {<br />  MATRIX ret;<br />  for(int y=0;y&lt;4;y++){<br />   for(int x=0;x&lt;4;x++){<br />    ret.mat_16[y*4+x]=mat.mat_16[y*4]*this-&gt;mat_16[x]+mat.mat_16[y*4+1]*this-&gt;mat_16[x+4]+mat.mat_16[y*4+2]*this-&gt;mat_16[x+8]+mat.mat_16[y*4+3]*this-&gt;mat_16[x+12];<br />   }<br />  }<br />  return ret;<br /> }</p> <p>float SGN(float x) {<br />  return (x &gt;= 0.0f) ? +1.0f : -1.0f;<br /> }</p> <p>//回転行列をクォータニオンにする<br /> QUATERNION MATRIX::ToQuaternion(){<br />  QUATERNION q;<br />  q.w = ( this-&gt;_11 + this-&gt;_22 + this-&gt;_33 + 1.0f) / 4.0f;<br />  q.x = ( this-&gt;_11 - this-&gt;_22 - this-&gt;_33 + 1.0f) / 4.0f;<br />  q.y = (-this-&gt;_11 + this-&gt;_22 - this-&gt;_33 + 1.0f) / 4.0f;<br />  q.z = (-this-&gt;_11 - this-&gt;_22 + this-&gt;_33 + 1.0f) / 4.0f;<br />  for(int i=0;i&lt;4;i++){<br />   if(q.Index[i] &lt; 0.0f) q.Index[i] = 0.0f;<br />   q.Index[i] = sqrt(q.Index[i]);<br />  }<br />  if(q.w &gt;= q.x &amp;&amp; q.w &gt;= q.y &amp;&amp; q.w &gt;= q.z) {<br />   q.w *= +1.0f;<br />   q.x *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />   q.y *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />   q.z *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />  } else {<br />   q.w *= +1.0f*-1;<br />   q.x *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />   q.y *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />   q.z *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />  }</p> <p> float nor = sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z *q.z);<br />  for(int i=0;i&lt;4;i++){<br />   q.Index[i] /= nor;<br />  }<br />  return q;<br /> }</p> <p>//クォータニオンを回転行列にする<br /> MATRIX QUATERNION::ToMatrix(){<br />  MATRIX ret;<br />     float sx = this-&gt;x * this-&gt;x;<br />     float sy = this-&gt;y * this-&gt;y;<br />     float sz = this-&gt;z * this-&gt;z;<br />     float cx = this-&gt;y * this-&gt;z;<br />     float cy = this-&gt;x * this-&gt;z;<br />     float cz = this-&gt;x * this-&gt;y;<br />     float wx = this-&gt;w * this-&gt;x;<br />     float wy = this-&gt;w * this-&gt;y;<br />     float wz = this-&gt;w * this-&gt;z;</p> <p> ret._11= 1.0f - 2.0f * (sy + sz);<br />  ret._12= 2.0f * (cz + wz);<br />  ret._13= 2.0f * (cy - wy);<br />  ret._21= 2.0f * (cz - wz);<br />  ret._22= 1.0f - 2.0f * (sx + sz);<br />  ret._23= 2.0f * (cx + wx);<br />  ret._31= 2.0f * (cy + wy);<br />  ret._32= 2.0f * (cx - wx);<br />  ret._33= 1.0f - 2.0f * (sx + sy);<br />  ret._41= 0.0f;<br />  ret._42= 0.0f;<br />  ret._43= 0.0f;<br />  return ret;<br /> }</p> <p>//3つのベクトル<br /> struct Vector3f{<br />  float x;<br />  float y;<br />  float z;<br />  Vector3f(){};<br />  Vector3f(float _x,float _y,float _z){<br />   x=_x;y=_y;z=_z;<br />  };<br /> }vec3d;<br /> Vector3f &amp; operator*(Vector3f &amp;v,float size){<br />  v.x *= size;<br />  v.y *= size;<br />  v.z *= size;<br />  return v;<br /> }<br /> Vector3f &amp; operator+(Vector3f &amp;a,Vector3f &amp;b){<br />  a.x+=b.x;<br />  a.y+=b.y;<br />  a.z+=b.z;<br />  return a;<br /> }<br /> //4つのベクトル<br /> struct Vector4f{<br />  union {<br />         struct {<br />    float x;<br />    float y;<br />    float z;<br />    float w;<br />   };<br />   float Index[4];<br />  };<br />  Vector4f(){};<br />  Vector4f(float _x,float _y,float _z,float _w){<br />   x=_x;y=_y;z=_z;w=_w;<br />  };<br />  Vector4f GeometricTransform(MATRIX&amp; mat);//幾何変換<br /> }vec4d;<br /> Vector4f Vector4f::GeometricTransform(MATRIX &amp;mat){<br />  Vector4f ret;<br />  for(int y=0;y&lt;4;y++){<br />   ret.Index[y]=mat.mat_16[y]*this-&gt;x+mat.mat_16[y+4]*this-&gt;y+mat.mat_16[y+8]*this-&gt;z+mat.mat_16[y+12]*this-&gt;w;<br />  }<br />  return ret;<br /> }<br /> //正規化<br /> void normalize(Vector3f&amp; v){<br />  float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);<br />  if(m &gt; 0.0f){m = 1.0f / m;}else{m = 0.0f;}<br />  v.x*=m;<br />  v.y*=m;<br />  v.z*=m;<br /> }<br /> //外積<br /> void cross( Vector3f&amp; src1, Vector3f&amp; src2 ,Vector3f&amp; dst){<br />  dst.x = src1.y*src2.z - src1.z*src2.y;<br />  dst.y = src1.z*src2.x - src1.x*src2.z;<br />  dst.z = src1.x*src2.y - src1.y*src2.x;<br /> }<br /> //内積<br /> void dot(Vector3f&amp; src1,Vector3f&amp; src2,float&amp; dst){<br />  dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;<br /> }</p> <p>//4つのカラー<br /> struct Color4{<br />  float r;<br />  float g;<br />  float b;<br />  float a;<br /> };<br /> //4つの反射<br /> struct Reflection4{<br />  Color4 diffuse;<br />  Color4 ambient;<br />  Color4 emission;<br />  Color4 specular;<br /> };<br /> //UV座標<br /> struct UV{<br />  float u;//u値<br />  float v;//v値<br /> }vec2d;<br /> //ポリゴンデータ<br /> struct Triangle{<br />  Vector3f TriVer;<br />  Vector3f TriNor;<br />  UV TriUV;<br />  Vector3f TriView;<br /> }Tri;<br /> //ポリゴンデータ<br /> struct Quadrangle{<br />  Vector3f QuadVer;<br />  Vector3f QuadNor;<br />  UV QuadUV;<br /> }Quad;<br /> //フレーム外マテリアル構造体<br /> struct OUTSIDEMATERIAL{<br />  string MaterialName;//マテリアル名<br />  Reflection4 MaterialColor;//反射<br />  float Shininess;//shininess<br />  string TextureName;//テクスチャ名<br />  int TexNo;//テクスチャNO.<br /> }outmtl;<br /> //マテリアル構造体<br /> struct MATERIAL{<br />  string MaterialName;//マテリアル名<br />  Reflection4 MaterialColor;//反射<br />  float Shininess;//shininess<br />  string TextureName;//テクスチャ名<br />  int TexNo;//テクスチャNO.<br />  vector &lt;Triangle&gt; Tridata;//三角面データ<br />  vector &lt;Quadrangle&gt; Quaddata;//四角面データ<br /> }mtl;<br /> //メッシュ構造体<br /> struct MESH{<br /> public:<br />  vector &lt;MATERIAL&gt; Material;//マテリアル<br />  vector &lt;TEXTURE*&gt; TexData;//テクスチャデータ<br />  vector&lt;GLuint&gt; TexID;//テクスチャID<br />  GLuint TexID2;//代入用<br />  TEXTURE* tex;//代入用<br /> }msh;<br /> //ボーン構造体<br /> struct BONE{<br /> public:<br />  string Bone_Name;//ボーン名<br />  vector&lt;int&gt;SkinID;//スキンインデックス<br />  vector&lt;float&gt;SkinWeights;//スキンウェイト<br />  MATRIX bone_ofset;//ボーンオフセット行列<br />  MATRIX CurrentFrame;//現在の行列<br /> }bne;<br /> //アニメーションデータ構造体<br /> struct ANIMATION{<br /> public:<br />  vector &lt;int&gt; Key;//アニメーションキー<br />  vector &lt;MATRIX&gt; Matrix;//行列データ<br /> }anm;<br /> //ノード構造体<br /> struct NODE{<br />  NODE* Node;//子ノード<br />  NODE* Next;//隣の階層<br />  string FrameName;//フレーム名<br />  MESH* Mesh;//メッシュ<br />  BONE* Bone;//ボーン<br />  vector&lt;GLuint&gt; MatNo;//マテリアルNO.<br />  ANIMATION Anim;//アニメーションデータ<br />  MATRIX FrameTransformMatrix;//親フレームからのトランスフォーム行列<br /> }nde;<br /> //階層メッシュクラス<br /> class HIERARCHY{<br /> public:<br />  void Draw();//描画<br />  void Draw_Frame(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//フレーム描画<br />  void Animation_Draw(int Animation_NO,int Frame);//アニメーション描画<br />  HIERARCHY();<br />  HIERARCHY(char* FileName,float size);<br />  NODE Root;//ルートノード<br />  float Size;//サイズ<br />  int Animation_MaxFrame;//最大フレーム<br /> private:<br />  bool Load_Mesh(FILE&amp; fp,NODE&amp; node);//メッシュ読み込み<br />  QUATERNION Spherical_Linear_Interpolation( QUATERNION&amp; q1, QUATERNION&amp; q2, float t);//球面線形補間<br />  char buffer[255];<br /> protected:<br />  NODE* pNode;//ノードポインタ<br />  int Back;//階層戻し<br />  void Init();<br />  bool Load_Hierarchy(char* FileName); //階層メッシュ読み込み<br />  bool Load_Frame(FILE&amp; fp,NODE&amp; node,int&amp; hierarchy);  //フレーム読み込み<br />  bool Load_Animation(FILE&amp; fp);//アニメーション読み込み<br />  void Find_Frame(NODE&amp; node,char* name);//フレームを探す<br />  MATRIX Linear_Interpolation(MATRIX&amp; a,MATRIX&amp; b,float t);//線形補間<br />  vector&lt;OUTSIDEMATERIAL&gt; OutSide_Mat;//フレーム外マテリアル<br />  vector&lt;BONE&gt; Bone;//ボーン情報<br />  vector&lt;Vector3f&gt; Vertex;//頂点グループ<br />  vector&lt;Vector3f&gt; VertexView;//頂点グループ<br />  vector&lt;Vector3f&gt; Normal;//法線グループ<br />  vector&lt;int&gt; VertexIndex;//頂点インデックス<br />  vector&lt;int&gt; FaceIndex;//面インデックス<br />  vector&lt;int&gt; NormalIndex;//法線インデックス<br />  vector&lt;int&gt; MaterialIndex;//マテリアルインデックス<br />  vector&lt;UV&gt; uv;//UV<br />  void DataCreate(NODE&amp; node);<br />  void ViewDataCreate(NODE&amp; node);<br /> };<br /> //スキンメッシュクラス<br /> class SKINNEDMESH : public HIERARCHY{<br />  public:<br />   bool SkinnedMeshFlag;//スキンメッシュか階層メッシュか<br />   int AnimTicksPerSecond;//一秒間のコマ数<br />   bool Load_SkinnedMesh(char* FileName, float size);//スキンメッシュ読み込み<br />   SKINNEDMESH();<br />   SKINNEDMESH(char* FileName,float size);<br />   float Draw_Joint(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//ジョイント描画<br />   void Draw_Bone(MATRIX mat,float length);//ボーン描画<br />   void Calc_Bone(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//ボーン計算<br /> };<br /> SKINNEDMESH::SKINNEDMESH(){<br />  SkinnedMeshFlag=false;<br />  AnimTicksPerSecond=60;<br />  Size=1;<br />  Animation_MaxFrame=0;<br /> }<br /> SKINNEDMESH::SKINNEDMESH(char *FileName, float size){<br />  //階層メッシュアニメーションかスキンメッシュアニメーションかの判定<br />  char key[255];<br />  FILE* fp=NULL;<br />  SkinnedMeshFlag=false;<br />  AnimTicksPerSecond=60;<br />  Animation_MaxFrame=0;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  while(!feof(fp)){<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(fp,"%s ",key,sizeof(key));<br />   //テンプレート読み飛ばし<br />   if(strcmp(key,"template")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   if(strcmp(key,"AnimTicksPerSecond")==0){<br />    fgets(key,sizeof(key),fp);<br />    fscanf_s(fp,"%d;",&amp;AnimTicksPerSecond);<br />   }<br />   if((strcmp(key,"FrameTransformMatrix")==0)||(strcmp(key,"XSkinMeshHeader")==0)||<br />    (strcmp(key,"VertexDuplicationIndices")==0)||(strcmp(key,"SkinWeights")==0)){<br />     SkinnedMeshFlag=true;<br />   }<br />  }<br />  if(SkinnedMeshFlag){//スキンメッシュアニメーションなら<br />   Init();<br />   Size=size;<br />   Load_SkinnedMesh(FileName,size);<br />  }else{//階層メッシュアニメーションなら<br />  Init();<br />  Size=size;<br />  this-&gt;Load_Hierarchy(FileName);<br />  }<br /> }</p> <p>//データ作成<br /> void HIERARCHY::ViewDataCreate(NODE&amp; node){<br />  int Count=0;<br />     //マテリアル毎のデータを作成<br />     for(int i=0;i&lt;(signed)MaterialIndex.size();i++){<br />      if(FaceIndex[i]==3){<br />       for(int j=0;j&lt;3;j++){<br />        Tri.TriVer=VertexView[VertexIndex[Count+j]];<br />        Tri.TriNor=Normal[NormalIndex[Count+j]];<br />        //Tri.TriUV=uv[VertexIndex[Count+j]];<br />     Tri.TriView=VertexView[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Tridata[Count+j]=Tri;<br />       }<br />       Count+=3;<br />      }else{<br />       for(int j=0;j&lt;4;j++){<br />        Quad.QuadVer=Vertex[VertexIndex[Count+j]];<br />        Quad.QuadNor=Normal[NormalIndex[Count+j]];<br />        //Quad.QuadUV=uv[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Quaddata.push_back(Quad);<br />       }<br />       Count+=4;<br />      }<br />     }<br /> }<br /> //ボーン計算<br /> void SKINNEDMESH::Calc_Bone(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  MATRIX current=mat;<br />  while(1){<br />   if(node.Bone!=NULL){<br />    if(node.Anim.Key.size()==0){<br />     mat=mat.Multiplication(node.FrameTransformMatrix);<br />    }else{<br />     //線形補間<br />     for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />      int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />      int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />      float t=(float)Current/(float)Length;<br />      if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />       MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />       mat=mat.Multiplication(Linear);<br />      }<br />     }<br />    }<br />    for(int i=0;i&lt;Bone.size();i++){<br />     if(node.Bone-&gt;Bone_Name==Bone[i].Bone_Name)Bone[i].CurrentFrame=mat;<br />    }<br />   }<br />   //スキンメッシュアニメーションの具体的な処理↓(わかりやすくするため、あえてこのような記述にしてあります。)<br />   if(node.Mesh!=NULL){<br />    for(int i=0;i&lt;Vertex.size();i++){<br />     vec4d.x=Vertex[i].x;vec4d.y=Vertex[i].y;vec4d.z=Vertex[i].z;vec4d.w=1.0;<br />     Vector4f ret8=vec4d.GeometricTransform(Bone[3].bone_ofset);<br />     Vector4f ret7=ret8.GeometricTransform(Bone[3].CurrentFrame);<br />     Vector4f ret6=vec4d.GeometricTransform(Bone[2].bone_ofset);<br />     Vector4f ret5=ret6.GeometricTransform(Bone[2].CurrentFrame);<br />     Vector4f ret4=vec4d.GeometricTransform(Bone[1].bone_ofset);<br />     Vector4f ret3=ret4.GeometricTransform(Bone[1].CurrentFrame);<br />     Vector4f ret2=vec4d.GeometricTransform(Bone[0].bone_ofset);<br />     Vector4f ret=ret2.GeometricTransform(Bone[0].CurrentFrame);<br />     vec3d.x=ret.x*Bone[0].SkinWeights[i]+ret3.x*Bone[1].SkinWeights[i]+ret5.x*Bone[2].SkinWeights[i]+ret7.x*Bone[3].SkinWeights[i];<br />     vec3d.y=ret.y*Bone[0].SkinWeights[i]+ret3.y*Bone[1].SkinWeights[i]+ret5.y*Bone[2].SkinWeights[i]+ret7.y*Bone[3].SkinWeights[i];<br />     vec3d.z=ret.z*Bone[0].SkinWeights[i]+ret3.z*Bone[1].SkinWeights[i]+ret5.z*Bone[2].SkinWeights[i]+ret7.z*Bone[3].SkinWeights[i];<br />     VertexView[i]=vec3d;<br />    }<br />    ViewDataCreate(node);<br />   }<br />   if(node.Node!=NULL)Calc_Bone(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)Calc_Bone(*node.Next,Frame_Time,current);<br />   return;<br />  }<br />  return;<br /> }<br /> //ボーン描画<br /> void SKINNEDMESH::Draw_Bone(MATRIX mat,float length){<br />  glColor4f(0.0f,1.0f,1.0f,1.0f);<br />  glPushMatrix();<br />  glMultMatrixf(&amp;mat.mat_16[0]);<br />  glRotatef(90.0f,1.0f,0.0f,0.0f);<br />  if(mat._41+mat._42+mat._43!=0){<br />   if(length!=0)glutSolidCone(10.0f*Size, length, 4, 1);<br />  }<br />  glPopMatrix();<br /> }<br /> //ジョイント描画<br /> float SKINNEDMESH::Draw_Joint(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);<br />  glEnable(GL_COLOR_MATERIAL);<br />  MATRIX current=mat;<br />  MATRIX ret;<br />  float length=0;<br />  while(1){<br />   if(node.Bone!=NULL){<br />    glPushMatrix();<br />    if(node.Anim.Key.size()==0){<br />     mat=mat.Multiplication(node.FrameTransformMatrix);<br />    }else{<br />     //線形補間<br />     for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />      int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />      int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />      float t=(float)Current/(float)Length;<br />      if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />       MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />       mat=mat.Multiplication(Linear);<br />      }<br />     }<br />    }<br />    glMultMatrixf(&amp;mat.mat_16[0]);<br />    glColor4f(1.0f,1.0f,0.0f,1.0f);<br />    glutSolidSphere(5.0*Size,8,8);<br />    ret=mat;<br />    length=-sqrt((current._41-mat._41)*(current._41-mat._41)+(current._42-mat._42)*(current._42-mat._42)+(current._43-mat._43)*(current._43-mat._43));<br />    glPopMatrix();<br />   }</p> <p>  float len=0;<br />   if(node.Node!=NULL)len=Draw_Joint(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)len=Draw_Joint(*node.Next,Frame_Time,current);<br />   Draw_Bone(ret,len);<br />   return length;<br />  }<br />  glDisable(GL_COLOR_MATERIAL);<br />  return 0;<br /> }</p> <p><br /> bool SKINNEDMESH::Load_SkinnedMesh(char *FileName, float size){<br />  //Xファイルを開いて内容を読み込む<br />  Back=-1;<br />  int Hierarchy=0;<br />  FILE* fp=NULL;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  Load_Frame(*fp,Root,Hierarchy);<br />  //ボーン情報をセット<br />  for(int i=0;i&lt;(signed)Bone.size();i++){<br />   Find_Frame(Root,(char*)Bone[i].Bone_Name.c_str());<br />   pNode-&gt;Bone=&amp;Bone[i];<br />  }<br />  fseek(fp,0,SEEK_SET);<br />  this-&gt;Load_Animation(*fp);<br />  fclose(fp);</p> <p> return true;<br /> }</p> <p>//コンストラクタ<br /> HIERARCHY::HIERARCHY(){<br />  Init();<br /> }<br /> //コンストラクタ<br /> HIERARCHY::HIERARCHY(char* FileName,float size){<br />  Init();<br />  Size=size;<br />  Animation_MaxFrame=0;<br />  Load_Hierarchy(FileName);<br /> }<br /> //初期化<br /> void HIERARCHY::Init(){<br />  Root.Node=NULL;<br />  Root.Next=NULL;<br />  Root.FrameName="Root";<br />  Root.Mesh=NULL;<br />  Root.Bone=NULL;<br /> }</p> <p>//球面線形補間<br /> QUATERNION HIERARCHY::Spherical_Linear_Interpolation( QUATERNION&amp; q1, QUATERNION&amp; q2, float t)<br /> {<br />   QUATERNION q;<br />     if((q1.w==q2.w)&amp;&amp;(q1.x==q2.x)&amp;&amp;(q1.y==q2.y)&amp;&amp;(q1.z==q2.z)){<br />    for(int i=0;i&lt;4;i++){<br />     q.Index[i] = q1.Index[i];<br />    }<br />    return q;<br />   }<br />   float qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;<br />   float ss = 1.0f - qr * qr;<br />  <br />   if (ss == 0.0f) {<br />    for(int i=0;i&lt;4;i++){<br />     q.Index[i] = q1.Index[i];<br />    }<br />    return q;<br />   }else{<br />     float sp = sqrt(ss);<br />     float ph = acos(qr);<br />     float pt = ph * t;<br />     float t1 = sin(pt) / sp;<br />     float t0 = sin(ph - pt) / sp;</p> <p> for(int i=0;i&lt;4;i++){<br />   q.Index[i] = (q1.Index[i] * t0 + q2.Index[i] * t1);<br />  }<br />  return q;<br />   }<br /> }</p> <p>//線形補間<br /> MATRIX HIERARCHY::Linear_Interpolation(MATRIX&amp; a,MATRIX&amp; b,float t){<br />  MATRIX ret,r1,r2,r3;<br />  QUATERNION q1,q2,q3;<br />  Vector3f vec_A, vec_B, vec_R;<br />  //平行移動<br />  vec_A.x=a._41;<br />  vec_A.y=a._42;<br />  vec_A.z=a._43;<br />  vec_B.x=b._41;<br />  vec_B.y=b._42;<br />  vec_B.z=b._43;<br />  vec_R=vec_A*(1.0f-t) + vec_B*t;<br />  ret._41=vec_R.x;<br />  ret._42=vec_R.y;<br />  ret._43=vec_R.z;<br />  //スケーリング成分抜き出し<br />  vec_A.x=sqrt(a._11*a._11+a._21*a._21+a._31*a._31);<br />  vec_A.y=sqrt(a._12*a._12+a._22*a._22+a._32*a._32);<br />  vec_A.z=sqrt(a._13*a._13+a._23*a._23+a._33*a._33);<br />  vec_B.x=sqrt(b._11*b._11+b._21*b._21+b._31*b._31);<br />  vec_B.y=sqrt(b._12*b._12+b._22*b._22+b._32*b._32);<br />  vec_B.z=sqrt(b._13*b._13+b._23*b._23+b._33*b._33);<br />  <br />  for(int i=0;i&lt;4;i++){<br />   for(int j=0;j&lt;4;j++){<br />    r1.mat_4x4[j][i]=a.mat_4x4[j][i];<br />    r2.mat_4x4[j][i]=b.mat_4x4[j][i];<br />    if(i==0){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.x;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.x;}}<br />    if(i==1){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.y;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.y;}}<br />    if(i==2){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.z;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.z;}}<br />   }<br />  }<br />  <br />  //クォータニオンを補間<br />  q1=r1.ToQuaternion();<br />  q2=r2.ToQuaternion();<br />  q3=Spherical_Linear_Interpolation(q1,q2,t);<br />  r3=q3.ToMatrix();<br />  <br />  vec_R=vec_A*(1.0f-t) + vec_B*t;<br />  ret._11=r3._11*vec_R.x;<br />  ret._21=r3._21*vec_R.x;<br />  ret._31=r3._31*vec_R.x;<br />  ret._12=r3._12*vec_R.y;<br />  ret._22=r3._22*vec_R.y;<br />  ret._32=r3._32*vec_R.y;<br />  ret._13=r3._13*vec_R.z;<br />  ret._23=r3._23*vec_R.z;<br />  ret._33=r3._33*vec_R.z;</p> <p> return ret;<br /> }<br /> //フレーム描画<br /> void HIERARCHY::Draw_Frame(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  MATRIX current=mat;<br />  while(1){<br />   if(node.Mesh!=NULL){<br />    glEnableClientState(GL_VERTEX_ARRAY);<br />    glEnableClientState(GL_NORMAL_ARRAY);<br />    glPushMatrix();<br />    glMultMatrixf(&amp;mat.mat_16[0]);<br />    //線形補間<br />    for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />     int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />     int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />     float t=(float)Current/(float)Length;<br />     if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />      MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />      mat=mat.Multiplication(Linear);<br />      glMultMatrixf(&amp;Linear.mat_16[0]);<br />     }<br />    }<br />    for(int i=0;i&lt;(signed)node.Mesh-&gt;Material.size();i++){<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.ambient);<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.diffuse);<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.specular);<br />     glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,node.Mesh-&gt;Material[i].Shininess);</p> <p>    if(node.Mesh-&gt;Material[i].TexNo&gt;0){<br />      glEnableClientState(GL_TEXTURE_COORD_ARRAY);<br />      glEnable(GL_TEXTURE_2D);<br />      glBindTexture(GL_TEXTURE_2D, node.Mesh-&gt;TexID[node.Mesh-&gt;Material[i].TexNo-1]);<br />     }else{<br />      glDisable(GL_TEXTURE_2D);<br />      glDisableClientState(GL_TEXTURE_COORD_ARRAY);<br />     }<br />    <br />     if(node.Mesh-&gt;Material[i].Tridata.size()&gt;1){<br />      //glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &amp;node.Mesh-&gt;Material[i].Tridata[0].TriVer.x);<br />   glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &amp;node.Mesh-&gt;Material[i].Tridata[0].TriView.x);<br />      glNormalPointer(GL_FLOAT,sizeof(Tri),&amp;node.Mesh-&gt;Material[i].Tridata[0].TriNor.x);<br />      //if(node.Mesh-&gt;Material[i].TexNo&gt;0)glTexCoordPointer(2, GL_FLOAT, sizeof(Tri), &amp;node.Mesh-&gt;Material[i].Tridata[0].TriUV.u);<br />      glDrawArrays(GL_TRIANGLES,0,node.Mesh-&gt;Material[i].Tridata.size());<br />     }<br />     if(node.Mesh-&gt;Material[i].Quaddata.size()&gt;1){<br />      glVertexPointer(3, GL_FLOAT,sizeof(Quad) , &amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadVer.x);<br />      glNormalPointer(GL_FLOAT,sizeof(Quad),&amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadNor.x);<br />      //if(node.Mesh-&gt;Material[i].TexNo&gt;0)glTexCoordPointer(2, GL_FLOAT, sizeof(Quad), &amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadUV.u);<br />      glDrawArrays(GL_QUADS,0,node.Mesh-&gt;Material[i].Quaddata.size());<br />     }<br />  <br />    }<br />    glDisableClientState(GL_VERTEX_ARRAY);<br />    glDisableClientState(GL_NORMAL_ARRAY);<br />    //glDisableClientState(GL_TEXTURE_COORD_ARRAY);<br />    //glDisable(GL_TEXTURE_2D);<br />    glPopMatrix();<br />   }</p> <p>  if(node.Node!=NULL)Draw_Frame(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)Draw_Frame(*node.Next,Frame_Time,current);<br />   if(node.Node==NULL)return;<br />   if(node.Next==NULL)return;<br />   return;<br />  }<br /> }<br /> //アニメーション描画<br /> void HIERARCHY::Animation_Draw(int Animation_NO,int Frame){<br />  MATRIX mat;<br />  Draw_Frame(Root,Frame,mat);<br /> }<br /> //描画<br /> void HIERARCHY::Draw(){<br />  MATRIX mat;<br />  Draw_Frame(Root,0,mat);<br /> }<br /> //フレームを探す<br /> void HIERARCHY::Find_Frame(NODE&amp; node,char* name){<br />  while(1){<br />   if(strcmp(node.FrameName.c_str(),name)==0){<br />    pNode=&amp;node;<br />    return;<br />   }<br />   if(node.Node!=NULL)Find_Frame(*node.Node,name);<br />   if(node.Next!=NULL)Find_Frame(*node.Next,name);<br />   if(node.Node==NULL)return;<br />   if(node.Next==NULL)return;<br />   return;<br />  }<br />  return;<br /> }<br /> //アニメーション読み込み<br /> bool HIERARCHY::Load_Animation(FILE&amp; fp){<br />  char buf[255];<br />  char name[255];<br />  char *next;<br />  int hierarchy=0,count=0,key=0,dummy=0,x=0,y=0,z=0,w=0;<br />  //合成行列<br />  MATRIX mix;</p> <p> //読み込み<br />  while(!feof(&amp;fp))<br />  {<br />   ZeroMemory(buf,sizeof(buf));<br />   fscanf_s(&amp;fp,"%s ",buf,sizeof(buf));<br />     //テンプレート読み飛ばし<br />   if(strcmp(buf,"template")==0){<br />    while(strcmp(buf,"}")){<br />     fscanf_s(&amp;fp,"%s ",buf,sizeof(buf));<br />    }<br />    continue;<br />   }<br />   //AnimationSetを探す<br />   if(strcmp(buf,"AnimationSet")==0){<br />     while(!feof(&amp;fp))<br />     {<br />      fgets(buf,sizeof(buf),&amp;fp);<br />      if((!strstr(buf,"Animation")==NULL)&amp;&amp;(strstr(buf,"Animation_")==NULL)){<br />       fgets(buf,sizeof(buf),&amp;fp);<br />       fgets(buf,sizeof(buf),&amp;fp);<br />       if((!strstr(buf,"{")==NULL)&amp;&amp;(!strstr(buf,"}")==NULL)){//名前の抽出<br />        sscanf_s(buf," { %s } ",&amp;name,sizeof(name));<br />        strtok_s( name, "}" ,&amp;next);<br />        pNode=NULL;<br />        Find_Frame(Root,name);<br />        while(!feof(&amp;fp)){<br />         fgets(buf,sizeof(buf),&amp;fp);<br />       if(!strstr(buf,"AnimationKey")==NULL){<br />        fgets(buf,sizeof(buf),&amp;fp);<br />        fgets(buf,sizeof(buf),&amp;fp);//キータイプ 4…行列タイプ]<br />        if(strstr(buf,"4;")==NULL)printf("対応していません");<br />        fgets(buf,sizeof(buf),&amp;fp);//キー数<br />        count=atoi(buf);<br />        for(int i=0;i&lt;count;i++){<br />         fscanf_s(&amp;fp,"%d;%d;",&amp;key,&amp;dummy);//キーの位置;データの数<br />         if((count-1==i)&amp;&amp;(Animation_MaxFrame&lt;key))Animation_MaxFrame=key;<br />         pNode-&gt;Anim.Key.push_back(key);<br />         if(dummy!=16)printf("対応していません");<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[0],&amp;mix.mat_16[1],&amp;mix.mat_16[2],&amp;mix.mat_16[3]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[4],&amp;mix.mat_16[5],&amp;mix.mat_16[6],&amp;mix.mat_16[7]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[8],&amp;mix.mat_16[9],&amp;mix.mat_16[10],&amp;mix.mat_16[11]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;mix.mat_16[12],&amp;mix.mat_16[13],&amp;mix.mat_16[14],&amp;mix.mat_16[15]);<br />         fgets(buf,sizeof(buf),&amp;fp);<br />         mix._41*=Size;<br />         mix._42*=Size;<br />         mix._43*=Size;<br />         pNode-&gt;Anim.Matrix.push_back(mix);<br />        }<br />        break;<br />       }<br />        }<br />       }<br />      }<br />     }<br />   }<br />  }<br />  return true;<br /> }<br /> //データ作成<br /> void HIERARCHY::DataCreate(NODE&amp; node){<br />  int Count=0;<br />     //マテリアル毎のデータを作成<br />     for(int i=0;i&lt;(signed)MaterialIndex.size();i++){<br />      if(FaceIndex[i]==3){<br />       for(int j=0;j&lt;3;j++){<br />        Tri.TriVer=Vertex[VertexIndex[Count+j]];<br />        Tri.TriNor=Normal[NormalIndex[Count+j]];<br />        //Tri.TriUV=uv[VertexIndex[Count+j]];<br />     Tri.TriView=Vertex[VertexIndex[Count+j]];<br />        if(MaterialIndex[i]&gt;=(signed)node.Mesh-&gt;Material.size()){<br />         mtl.MaterialName=this-&gt;OutSide_Mat[MaterialIndex[i]].MaterialName;<br />         mtl.MaterialColor=this-&gt;OutSide_Mat[MaterialIndex[i]].MaterialColor;<br />         mtl.Shininess=this-&gt;OutSide_Mat[MaterialIndex[i]].Shininess;<br />         node.Mesh-&gt;Material.push_back(mtl);<br />        }<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Tridata.push_back(Tri);<br />       }<br />       Count+=3;<br />      }else{<br />       for(int j=0;j&lt;4;j++){<br />        Quad.QuadVer=Vertex[VertexIndex[Count+j]];<br />        Quad.QuadNor=Normal[NormalIndex[Count+j]];<br />        //Quad.QuadUV=uv[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Quaddata.push_back(Quad);<br />       }<br />       Count+=4;<br />      }<br />     }<br /> }<br /> //メッシュ読み込み<br /> bool HIERARCHY::Load_Mesh(FILE&amp; fp,NODE&amp; node){<br />  char key[255];<br />  char buf[255];<br />  int v1=0,v2=0,v3=0,v4=0;<br />  int Count=0,matCount=0,Hierarchy=1;<br />  string str="";<br />  fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />  node.Mesh=NULL;<br />  //読み込み<br />  while(!feof(&amp;fp))<br />  {<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />   //階層+<br />   if(strcmp(key,"{")==0){<br />    Hierarchy++;<br />   }<br />   //階層-<br />   if(strcmp(key,"}")==0){<br />    Hierarchy--;<br />    if(Hierarchy==0){<br />     if(node.Mesh!=NULL)DataCreate(node);<br />     return true;<br />    }<br />   }<br />  <br />   if(strcmp(key,"Frame")==0){<br />  if(node.Mesh!=NULL)DataCreate(node);<br />     return true;<br />   }<br />  <br />   //頂点 読み込み<br />   if(strcmp(key,"Mesh")==0)<br />   {<br />    node.Mesh =new MESH(msh);<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     fscanf_s(&amp;fp,"%f;%f;%f;,",&amp;vec3d.x,&amp;vec3d.y,&amp;vec3d.z);<br />     Vertex.push_back(vec3d*(float)Size);<br />  VertexView.push_back(vec3d*(float)Size);<br />    }<br />    //頂点インデックス読み込み<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&amp;fp);}//空行対策<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     int dammy=0;<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     str=buf;<br />     string::size_type first = str.find_first_not_of(' ');<br />  string::size_type tab = str.find_first_not_of('\t');<br />     string::size_type index = str.find("3;");<br />     if(index-first-tab==0){<br />      sscanf_s(buf,"%d;%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3);<br />      VertexIndex.push_back(v1);<br />      VertexIndex.push_back(v2);<br />      VertexIndex.push_back(v3);<br />     }<br />     if(!(index-first-tab==0)){<br />      sscanf_s(buf,"%d;%d,%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3,&amp;v4);<br />      VertexIndex.push_back(v1);<br />      VertexIndex.push_back(v2);<br />      VertexIndex.push_back(v3);<br />      VertexIndex.push_back(v4);<br />     }<br />     FaceIndex.push_back(dammy);<br />    }<br />   }</p> <p>  //法線 読み込み<br />   if(strcmp(key,"MeshNormals")==0)<br />   {<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     fscanf_s(&amp;fp,"%f;%f;%f;,",&amp;vec3d.x,&amp;vec3d.y,&amp;vec3d.z);<br />     Normal.push_back(vec3d);<br />    }<br />    //法線インデックス読み込み<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&amp;fp);}//空行対策<br />    Count=atoi(buf); <br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     int dammy=0;<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     str=buf;<br />     string::size_type first = str.find_first_not_of(' ');<br />  string::size_type tab = str.find_first_not_of('\t');<br />     string::size_type index = str.find("3;");<br />     if(index-first-tab==0){<br />      sscanf_s(buf,"%d;%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3);<br />      NormalIndex.push_back(v1);<br />      NormalIndex.push_back(v2);<br />      NormalIndex.push_back(v3);<br />     }<br />     if(!(index-first-tab==0)){<br />      sscanf_s(buf,"%d;%d,%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3,&amp;v4);<br />      NormalIndex.push_back(v1);<br />      NormalIndex.push_back(v2);<br />      NormalIndex.push_back(v3);<br />      NormalIndex.push_back(v4);<br />     }<br />    }<br />   }</p> <p>  //マテリアルリスト<br />   if(strcmp(key,"MeshMaterialList")==0)<br />   {<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);//空改行<br />    fgets(buf,sizeof(buf),&amp;fp);//マテリアル数<br />    matCount=atoi(buf);<br />    fgets(buf,sizeof(buf),&amp;fp);//リスト要素数<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count;i++)<br />    {<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     int test=atoi(buf);<br />     MaterialIndex.push_back(test);<br />    }<br />    char *next;<br />    for(int i=0;i&lt;matCount;i++)<br />    {<br />     fgets(buf,sizeof(buf),&amp;fp);<br />  sscanf_s(buf," { %s } ",&amp;buf,sizeof(buf));<br />  strtok_s( buf, "}" ,&amp;next);<br />  for(int j=0;j&lt;(signed)this-&gt;OutSide_Mat.size();j++){<br />   if(strcmp(this-&gt;OutSide_Mat[j].MaterialName.c_str(),buf)==0)node.MatNo.push_back(j);<br />  }<br />    }<br />   }<br />  }<br />  return false;<br /> }<br /> //フレーム読み込み<br /> bool HIERARCHY::Load_Frame(FILE&amp; fp,NODE&amp; node,int&amp; hierarchy){<br />  char key[255];<br />  char *next;<br />  int begin=0,end=0;<br />  int current=hierarchy;//現在の階層<br />  int file_pos;<br />  int count;<br />  int ID=0;<br />  float skinweights=0.0f;<br />  MATRIX dum;</p> <p> while(!feof(&amp;fp))<br />  {<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />   //ヘッダー読み飛ばし<br />   if(strcmp(key,"Header")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   //テンプレート読み飛ばし<br />   if(strcmp(key,"template")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   //階層+<br />   if(strcmp(key,"{")==0){<br />    begin++;<br />   }<br />   //階層-<br />   if(strcmp(key,"}")==0){<br />    end++;<br />   }<br />   //マテリアル読み込み<br />   if(strcmp(key,"Material")==0)<br />   {<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    strtok_s( key, "\n" ,&amp;next);<br />    outmtl.MaterialName=key;<br />    fgets(key,sizeof(key),&amp;fp);<br />    //ディフューズ<br />    fscanf_s(&amp;fp,"%f;%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z,&amp;vec4d.w);<br />    outmtl.MaterialColor.diffuse=(const Color4 &amp;)vec4d;<br />    //SHININESS<br />    fscanf_s(&amp;fp,"%f;",&amp;outmtl.Shininess);<br />    //スペキュラー<br />    fscanf_s(&amp;fp,"%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z);<br />    outmtl.MaterialColor.specular=(const Color4 &amp;)vec4d;<br />    //エミッシブ<br />    fscanf_s(&amp;fp,"%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z);<br />    outmtl.MaterialColor.ambient=(const Color4 &amp;)vec4d;</p> <p>   this-&gt;OutSide_Mat.push_back(outmtl);<br />   }<br />   //ボーン<br />   if(strcmp(key,"SkinWeights")==0){<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    sscanf_s(key,"\"%s\";",&amp;key,sizeof(key));<br />    strtok_s( key, "\"" ,&amp;next);<br />    bne.Bone_Name=key;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fgets(key,sizeof(key),&amp;fp);<br />    count=atoi(key);<br />    for(int i=0;i&lt;count;i++){<br />     fscanf_s(&amp;fp,"%d,",&amp;ID);<br />     bne.SkinID.push_back(ID);<br />    }<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    for(int i=0;i&lt;count;i++){<br />     fscanf_s(&amp;fp,"%f,",&amp;skinweights);<br />     bne.SkinWeights.push_back(skinweights);<br />    }<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[0],&amp;dum.mat_16[1],&amp;dum.mat_16[2],&amp;dum.mat_16[3]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[4],&amp;dum.mat_16[5],&amp;dum.mat_16[6],&amp;dum.mat_16[7]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[8],&amp;dum.mat_16[9],&amp;dum.mat_16[10],&amp;dum.mat_16[11]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;dum.mat_16[12],&amp;dum.mat_16[13],&amp;dum.mat_16[14],&amp;dum.mat_16[15]);<br />    bne.bone_ofset=dum;<br />    Bone.push_back(bne);<br />    bne.SkinID.clear();<br />    bne.SkinWeights.clear();<br />   }<br />   //親フレームからのトランスフォーム行列<br />   if(strcmp(key,"FrameTransformMatrix")==0){<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[0],&amp;dum.mat_16[1],&amp;dum.mat_16[2],&amp;dum.mat_16[3]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[4],&amp;dum.mat_16[5],&amp;dum.mat_16[6],&amp;dum.mat_16[7]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[8],&amp;dum.mat_16[9],&amp;dum.mat_16[10],&amp;dum.mat_16[11]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;dum.mat_16[12],&amp;dum.mat_16[13],&amp;dum.mat_16[14],&amp;dum.mat_16[15]);<br />    node.FrameTransformMatrix=dum;<br />    node.FrameTransformMatrix._41*=Size;<br />    node.FrameTransformMatrix._42*=Size;<br />    node.FrameTransformMatrix._43*=Size;<br />   }<br />  <br />   //フレーム<br />   if(strcmp(key,"Frame")==0){<br />    fscanf_s(&amp;fp,"%s ",key,sizeof(key));</p> <p>   if(((begin==0)&amp;&amp;(end==0))||(end-begin==-1)){//子ノード追加<br />     node.Node=new NODE(nde);<br />     node.Node-&gt;FrameName=key;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Node);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     hierarchy++;<br />     Load_Frame(fp,*node.Node,hierarchy);//再帰呼び出し<br />    }</p> <p>   if(Back==current){//階層戻り先にきた場合、同一階層追加<br />     Back=-1;<br />     node.Next=new NODE(nde);<br />     node.Next-&gt;FrameName=buffer;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Next);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     Load_Frame(fp,*node.Next,current);//再帰呼び出し<br />    }<br />    if(end-begin&gt;0){//"}"が"{"より多い時は階層を戻る<br />     strcpy_s(buffer,255,key);<br />     Back=current-(end-begin);<br />     return true;<br />    }<br />  <br />    if((end-begin==0)&amp;&amp;((begin!=0)&amp;&amp;(end!=0))){//同一階層追加<br />     node.Next=new NODE(nde);<br />     node.Next-&gt;FrameName=key;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Next);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     Load_Frame(fp,*node.Next,current);//再帰呼び出し<br />    }<br />    //階層を戻る<br />    if((Back!=-1)&amp;&amp;(Back&lt;current))return true;<br />   }<br />  }<br />  return true;<br /> }<br /> //階層メッシュ読み込み<br /> bool HIERARCHY::Load_Hierarchy(char* FileName){<br />  //Xファイルを開いて内容を読み込む<br />  Back=-1;<br />  int Hierarchy=0;<br />  FILE* fp=NULL;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  Load_Frame(*fp,Root,Hierarchy);<br />  fseek(fp,0,SEEK_SET);<br />  Load_Animation(*fp);<br />  fclose(fp);<br />  return true;<br /> }</p> </td> </tr></tbody></table><div> </div> <div>main.cpp</div> <table cellspacing="1" cellpadding="1" width="600" border="1"><tbody><tr><td> <p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #include &lt;GL/freeglut/freeglut.h&gt;<br /> #include "xfile.h"<br /> #include "font.h"</p> <p>#define WIDTH 640<br /> #define HEIGHT 480</p> <p>float angle=0.0f;<br /> SKINNEDMESH* SkinMesh;</p> <p>GLFONT *font;<br /> wstring wstr;<br /> wchar_t wchar[255];<br /> int CurrentFrame;<br /> MATRIX mat;</p> <p>void display(void)<br /> {<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  glViewport(0,0,WIDTH,HEIGHT);<br />  glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  gluPerspective(30.0, WIDTH/HEIGHT, 0.1, 5000.0);<br />  glMatrixMode(GL_MODELVIEW);<br />  glLoadIdentity();<br />  gluLookAt(-1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);</p> <p> glRotatef(angle, 0.0f, 1.0f, 0.0f);<br />  SkinMesh-&gt;Calc_Bone(SkinMesh-&gt;Root,CurrentFrame,mat);<br />  glColor4f(1.0f,1.0f,1.0f,1.0f);</p> <p> glDisable(GL_LIGHTING);<br />  glDisable(GL_DEPTH_TEST);<br />  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);<br />  SkinMesh-&gt;Animation_Draw(0,CurrentFrame);<br />  SkinMesh-&gt;Draw_Joint(SkinMesh-&gt;Root,CurrentFrame,mat);<br />  glEnable(GL_DEPTH_TEST);<br />  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);<br />  glEnable(GL_LIGHTING);</p> <p> //SkinMesh-&gt;Animation_Draw(0,CurrentFrame);</p> <p> glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  glMatrixMode(GL_MODELVIEW);<br />  glLoadIdentity();<br />  glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);</p> <p> glColor4f(1.0f, 1.0f, 1.0f, 1.0f);<br />  wstr=L"最大フレーム[";<br />  _itow_s(SkinMesh-&gt;Animation_MaxFrame,wchar,255,10);<br />  wstr+=wchar;<br />  wstr+=L"]";<br />  font-&gt;DrawStringW(0,16,(wchar_t *)wstr.c_str());<br />  wstr=L"現在のフレーム[";<br />  _itow_s(CurrentFrame,wchar,255,10);<br />  wstr+=wchar;<br />  wstr+=L"]";<br />  font-&gt;DrawStringW(0,32,(wchar_t *)wstr.c_str());</p> <p> glutSwapBuffers();<br /> }<br /> void idle(void)<br /> {<br />  glutPostRedisplay();<br />  //angle+=0.2f;<br />  angle=100.0f;<br />  if(SkinMesh-&gt;Animation_MaxFrame&lt;CurrentFrame)CurrentFrame=0;<br /> }<br /> //タイマー<br /> void timer(int value) {<br />  CurrentFrame+=30;<br />  glutTimerFunc(10 , timer , 0);<br /> }</p> <p>void Init(){<br />  glClearColor(0.0, 0.0, 0.0, 1.0);<br />  glEnable(GL_BLEND);<br />  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);<br />  glEnable(GL_DEPTH_TEST);<br />  glEnable(GL_LIGHT0);<br />  glEnable(GL_LIGHTING);<br />  glEnable(GL_CULL_FACE);<br />  glCullFace(GL_BACK);</p> <p> SkinMesh = new SKINNEDMESH("box.x",1.0f);<br />  font = new GLFONT(L"MS明朝", 16);</p> <p>}<br /> int main(int argc, char *argv[])<br /> {<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutCreateWindow("スキンメッシュアニメーション");<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  glutTimerFunc(100 , timer , 0);<br />  Init();<br />  glutMainLoop();<br />  return 0;<br /> }</p> </td> </tr></tbody></table><div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <p> </p>
<div> <div><strong>.x のスキンメッシュアニメーションを読み込んで表示します。</strong></div> <div><strong>このプログラムは <a href="http://cdn21.atwikiimg.com/opengl?cmd=upload&amp;act=open&amp;pageid=235&amp;file=box.x">box.x</a> 専用です。</strong></div> <div><strong>わかりやすくするために敢えて、このようにしました。</strong></div> </div> <div> </div> <div><strong><img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&amp;act=open&amp;pageid=235&amp;file=skin.png" /></strong></div> <div>  </div> <div><strong>これで完成ではありません。</strong></div> <div><strong>法線を再設定してあげないと光の反射具合が変になってしまいます。</strong></div> <div><strong>詳しくは次回に回します。</strong></div> <div> </div> <div>font.h</div> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <div>#pragma once</div> <div>class GLFONT</div> <div>{</div> <div>public:</div> <div> HFONT Hfont;</div> <div> HDC Hdc;</div> <div> GLFONT(wchar_t *fontname, int size);</div> <div> void DrawStringW(int x,int y,wchar_t *format, ...);</div> <div>};</div> <div>//コンストラクタ フォント作成</div> <div>GLFONT::GLFONT(wchar_t *fontname, int size)</div> <div>{</div> <div> Hfont = CreateFontW(</div> <div>        size,      //フォント高さ</div> <div>        0,       //文字幅</div> <div>        0,       //テキストの角度</div> <div>        0,       //ベースラインとx軸との角度</div> <div>        FW_REGULAR,     //フォントの太さ</div> <div>        FALSE,      //イタリック体</div> <div>        FALSE,      //アンダーライン</div> <div>        FALSE,      //打ち消し線</div> <div>        SHIFTJIS_CHARSET,   //文字セット</div> <div>        OUT_DEFAULT_PRECIS,   //出力精度</div> <div>        CLIP_DEFAULT_PRECIS,  //クリッピング精度</div> <div>        ANTIALIASED_QUALITY,  //出力品質</div> <div>        FIXED_PITCH | FF_MODERN, //ピッチとファミリー</div> <div>        fontname);     //書体名</div> <div> </div> <div> Hdc = wglGetCurrentDC();</div> <div> SelectObject(Hdc, Hfont);</div> <div>}</div> <div>//ワイド文字列の描画</div> <div>void GLFONT::DrawStringW(int x,int y,wchar_t *format, ...)</div> <div>{</div> <div> wchar_t buf[256];</div> <div> va_list ap;</div> <div> int Length=0;</div> <div> int list=0;</div> <div> </div> <div> //ポインタがNULLの場合は終了</div> <div> if ( format == NULL )</div> <div>  return;</div> <div> </div> <div> //文字列変換</div> <div> va_start(ap, format);</div> <div> vswprintf_s(buf, format, ap);</div> <div> va_end(ap);</div> <div> </div> <div> Length = wcslen(buf);</div> <div> list = glGenLists(Length);</div> <div> for( int i=0; i <div>  wglUseFontBitmapsW(Hdc, buf[i], 1, list + (DWORD)i);</div> <div> }</div> <div> </div> <div> glDisable(GL_LIGHTING);</div> <div> glRasterPos2i(x, y);</div> <div> //ディスプレイリストで描画</div> <div> for( int i=0; i <div> {</div> <div>  glCallList(list + i);</div> <div> }</div> <div> glEnable(GL_LIGHTING);</div> <div> //ディスプレイリスト破棄</div> <div> glDeleteLists(list, Length);</div> <div> list = 0;</div> <div> Length = 0;</div> <div>}</div> </div> </div> </td> </tr></tbody></table><div> </div> <div> </div> <div>PNG.h</div> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <p>#pragma once<br /> #include "lodepng.h"</p> <p>//テクスチャクラス<br /> class TEXTURE{<br /> protected:<br />  LodePNG_Decoder decoder;//デコーダ<br />  unsigned char* buffer;//バッファ<br />  size_t buffersize, imagesize;//サイズ<br /> public:<br />  TEXTURE();<br />  TEXTURE(const char* FileName);//コンストラクタ<br />  void LOAD_PNG(const char* FileName);//PNG読み込み<br />  unsigned char* image;//イメージポインタ<br />  unsigned int Width,Height;//画像サイズ<br /> };<br /> TEXTURE::TEXTURE(){<br /> }<br /> TEXTURE::TEXTURE(const char* FileName){<br />  LOAD_PNG(FileName);<br /> }<br /> void TEXTURE::LOAD_PNG(const char* FileName){<br />  LodePNG_Decoder_init(&amp;decoder);<br />  //ロード<br />  LodePNG_loadFile(&amp;buffer, &amp;buffersize, FileName);<br />  //デコード<br />  LodePNG_decode(&amp;decoder, &amp;image, &amp;imagesize, buffer, buffersize);<br />  //幅,高さ<br />  Width = decoder.infoPng.width;Height = decoder.infoPng.height;<br /> }</p> </td> </tr></tbody></table><div> </div> <div>xfile.h</div> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <p>#pragma once<br /> #include "PNG.h"<br /> #include &lt;math.h&gt;</p> <p>#define PAI 3.14159</p> <p>using namespace std;<br /> struct MATRIX;<br /> //クォータニオン構造体<br /> struct QUATERNION{<br />  union {<br />   struct {<br />    float w;<br />    float x;<br />    float y;<br />    float z;<br />   };<br />   float Index[4];<br />  };<br />  MATRIX ToMatrix();//クォータニオンを回転行列にする<br /> }qua;</p> <p>//マトリクス構造体<br /> struct MATRIX {<br />     union {<br />         struct {<br />             float _11, _12, _13, _14;<br />             float _21, _22, _23, _24;<br />             float _31, _32, _33, _34;<br />             float _41, _42, _43, _44;<br />         };<br />         float mat_4x4[4][4];<br />         float mat_16[16];<br />     };<br />  MATRIX(){//単位行列に初期化<br />   for(int i=0;i&lt;16;i++){<br />    this-&gt;mat_16[i]=0;<br />   }<br />   this-&gt;_11=this-&gt;_22=this-&gt;_33=this-&gt;_44=1;<br />  }<br />  void PRINT(char* text){<br />   printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />    text,<br />    this-&gt;_11,this-&gt;_21,this-&gt;_31,this-&gt;_41,<br />    this-&gt;_12,this-&gt;_22,this-&gt;_32,this-&gt;_42,<br />    this-&gt;_13,this-&gt;_23,this-&gt;_33,this-&gt;_43,<br />    this-&gt;_14,this-&gt;_24,this-&gt;_34,this-&gt;_44);<br />  }</p> <p> MATRIX Multiplication(MATRIX&amp; mat);//合成<br />  QUATERNION ToQuaternion();//回転行列をクォータニオンにする<br /> };<br /> //合成<br /> MATRIX MATRIX::Multiplication(MATRIX&amp; mat)<br /> {<br />  MATRIX ret;<br />  for(int y=0;y&lt;4;y++){<br />   for(int x=0;x&lt;4;x++){<br />    ret.mat_16[y*4+x]=mat.mat_16[y*4]*this-&gt;mat_16[x]+mat.mat_16[y*4+1]*this-&gt;mat_16[x+4]+mat.mat_16[y*4+2]*this-&gt;mat_16[x+8]+mat.mat_16[y*4+3]*this-&gt;mat_16[x+12];<br />   }<br />  }<br />  return ret;<br /> }</p> <p>float SGN(float x) {<br />  return (x &gt;= 0.0f) ? +1.0f : -1.0f;<br /> }</p> <p>//回転行列をクォータニオンにする<br /> QUATERNION MATRIX::ToQuaternion(){<br />  QUATERNION q;<br />  q.w = ( this-&gt;_11 + this-&gt;_22 + this-&gt;_33 + 1.0f) / 4.0f;<br />  q.x = ( this-&gt;_11 - this-&gt;_22 - this-&gt;_33 + 1.0f) / 4.0f;<br />  q.y = (-this-&gt;_11 + this-&gt;_22 - this-&gt;_33 + 1.0f) / 4.0f;<br />  q.z = (-this-&gt;_11 - this-&gt;_22 + this-&gt;_33 + 1.0f) / 4.0f;<br />  for(int i=0;i&lt;4;i++){<br />   if(q.Index[i] &lt; 0.0f) q.Index[i] = 0.0f;<br />   q.Index[i] = sqrt(q.Index[i]);<br />  }<br />  if(q.w &gt;= q.x &amp;&amp; q.w &gt;= q.y &amp;&amp; q.w &gt;= q.z) {<br />   q.w *= +1.0f;<br />   q.x *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />   q.y *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />   q.z *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21);<br />  } else {<br />   q.w *= +1.0f*-1;<br />   q.x *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />   q.y *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />   q.z *= SGN(this-&gt;_23 - this-&gt;_32)*SGN(this-&gt;_31 - this-&gt;_13)*SGN(this-&gt;_12 - this-&gt;_21)*-1;<br />  }</p> <p> float nor = sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z *q.z);<br />  for(int i=0;i&lt;4;i++){<br />   q.Index[i] /= nor;<br />  }<br />  return q;<br /> }</p> <p>//クォータニオンを回転行列にする<br /> MATRIX QUATERNION::ToMatrix(){<br />  MATRIX ret;<br />     float sx = this-&gt;x * this-&gt;x;<br />     float sy = this-&gt;y * this-&gt;y;<br />     float sz = this-&gt;z * this-&gt;z;<br />     float cx = this-&gt;y * this-&gt;z;<br />     float cy = this-&gt;x * this-&gt;z;<br />     float cz = this-&gt;x * this-&gt;y;<br />     float wx = this-&gt;w * this-&gt;x;<br />     float wy = this-&gt;w * this-&gt;y;<br />     float wz = this-&gt;w * this-&gt;z;</p> <p> ret._11= 1.0f - 2.0f * (sy + sz);<br />  ret._12= 2.0f * (cz + wz);<br />  ret._13= 2.0f * (cy - wy);<br />  ret._21= 2.0f * (cz - wz);<br />  ret._22= 1.0f - 2.0f * (sx + sz);<br />  ret._23= 2.0f * (cx + wx);<br />  ret._31= 2.0f * (cy + wy);<br />  ret._32= 2.0f * (cx - wx);<br />  ret._33= 1.0f - 2.0f * (sx + sy);<br />  ret._41= 0.0f;<br />  ret._42= 0.0f;<br />  ret._43= 0.0f;<br />  return ret;<br /> }</p> <p>//3つのベクトル<br /> struct Vector3f{<br />  float x;<br />  float y;<br />  float z;<br />  Vector3f(){};<br />  Vector3f(float _x,float _y,float _z){<br />   x=_x;y=_y;z=_z;<br />  };<br /> }vec3d;<br /> Vector3f &amp; operator*(Vector3f &amp;v,float size){<br />  v.x *= size;<br />  v.y *= size;<br />  v.z *= size;<br />  return v;<br /> }<br /> Vector3f &amp; operator+(Vector3f &amp;a,Vector3f &amp;b){<br />  a.x+=b.x;<br />  a.y+=b.y;<br />  a.z+=b.z;<br />  return a;<br /> }<br /> //4つのベクトル<br /> struct Vector4f{<br />  union {<br />         struct {<br />    float x;<br />    float y;<br />    float z;<br />    float w;<br />   };<br />   float Index[4];<br />  };<br />  Vector4f(){};<br />  Vector4f(float _x,float _y,float _z,float _w){<br />   x=_x;y=_y;z=_z;w=_w;<br />  };<br />  Vector4f GeometricTransform(MATRIX&amp; mat);//幾何変換<br /> }vec4d;<br /> Vector4f Vector4f::GeometricTransform(MATRIX &amp;mat){<br />  Vector4f ret;<br />  for(int y=0;y&lt;4;y++){<br />   ret.Index[y]=mat.mat_16[y]*this-&gt;x+mat.mat_16[y+4]*this-&gt;y+mat.mat_16[y+8]*this-&gt;z+mat.mat_16[y+12]*this-&gt;w;<br />  }<br />  return ret;<br /> }<br /> //正規化<br /> void normalize(Vector3f&amp; v){<br />  float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);<br />  if(m &gt; 0.0f){m = 1.0f / m;}else{m = 0.0f;}<br />  v.x*=m;<br />  v.y*=m;<br />  v.z*=m;<br /> }<br /> //外積<br /> void cross( Vector3f&amp; src1, Vector3f&amp; src2 ,Vector3f&amp; dst){<br />  dst.x = src1.y*src2.z - src1.z*src2.y;<br />  dst.y = src1.z*src2.x - src1.x*src2.z;<br />  dst.z = src1.x*src2.y - src1.y*src2.x;<br /> }<br /> //内積<br /> void dot(Vector3f&amp; src1,Vector3f&amp; src2,float&amp; dst){<br />  dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;<br /> }</p> <p>//4つのカラー<br /> struct Color4{<br />  float r;<br />  float g;<br />  float b;<br />  float a;<br /> };<br /> //4つの反射<br /> struct Reflection4{<br />  Color4 diffuse;<br />  Color4 ambient;<br />  Color4 emission;<br />  Color4 specular;<br /> };<br /> //UV座標<br /> struct UV{<br />  float u;//u値<br />  float v;//v値<br /> }vec2d;<br /> //ポリゴンデータ<br /> struct Triangle{<br />  Vector3f TriVer;<br />  Vector3f TriNor;<br />  UV TriUV;<br />  Vector3f TriView;<br /> }Tri;<br /> //ポリゴンデータ<br /> struct Quadrangle{<br />  Vector3f QuadVer;<br />  Vector3f QuadNor;<br />  UV QuadUV;<br /> }Quad;<br /> //フレーム外マテリアル構造体<br /> struct OUTSIDEMATERIAL{<br />  string MaterialName;//マテリアル名<br />  Reflection4 MaterialColor;//反射<br />  float Shininess;//shininess<br />  string TextureName;//テクスチャ名<br />  int TexNo;//テクスチャNO.<br /> }outmtl;<br /> //マテリアル構造体<br /> struct MATERIAL{<br />  string MaterialName;//マテリアル名<br />  Reflection4 MaterialColor;//反射<br />  float Shininess;//shininess<br />  string TextureName;//テクスチャ名<br />  int TexNo;//テクスチャNO.<br />  vector &lt;Triangle&gt; Tridata;//三角面データ<br />  vector &lt;Quadrangle&gt; Quaddata;//四角面データ<br /> }mtl;<br /> //メッシュ構造体<br /> struct MESH{<br /> public:<br />  vector &lt;MATERIAL&gt; Material;//マテリアル<br />  vector &lt;TEXTURE*&gt; TexData;//テクスチャデータ<br />  vector&lt;GLuint&gt; TexID;//テクスチャID<br />  GLuint TexID2;//代入用<br />  TEXTURE* tex;//代入用<br /> }msh;<br /> //ボーン構造体<br /> struct BONE{<br /> public:<br />  string Bone_Name;//ボーン名<br />  vector&lt;int&gt;SkinID;//スキンインデックス<br />  vector&lt;float&gt;SkinWeights;//スキンウェイト<br />  MATRIX bone_ofset;//ボーンオフセット行列<br />  MATRIX CurrentFrame;//現在の行列<br /> }bne;<br /> //アニメーションデータ構造体<br /> struct ANIMATION{<br /> public:<br />  vector &lt;int&gt; Key;//アニメーションキー<br />  vector &lt;MATRIX&gt; Matrix;//行列データ<br /> }anm;<br /> //ノード構造体<br /> struct NODE{<br />  NODE* Node;//子ノード<br />  NODE* Next;//隣の階層<br />  string FrameName;//フレーム名<br />  MESH* Mesh;//メッシュ<br />  BONE* Bone;//ボーン<br />  vector&lt;GLuint&gt; MatNo;//マテリアルNO.<br />  ANIMATION Anim;//アニメーションデータ<br />  MATRIX FrameTransformMatrix;//親フレームからのトランスフォーム行列<br /> }nde;<br /> //階層メッシュクラス<br /> class HIERARCHY{<br /> public:<br />  void Draw();//描画<br />  void Draw_Frame(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//フレーム描画<br />  void Animation_Draw(int Animation_NO,int Frame);//アニメーション描画<br />  HIERARCHY();<br />  HIERARCHY(char* FileName,float size);<br />  NODE Root;//ルートノード<br />  float Size;//サイズ<br />  int Animation_MaxFrame;//最大フレーム<br /> private:<br />  bool Load_Mesh(FILE&amp; fp,NODE&amp; node);//メッシュ読み込み<br />  QUATERNION Spherical_Linear_Interpolation( QUATERNION&amp; q1, QUATERNION&amp; q2, float t);//球面線形補間<br />  char buffer[255];<br /> protected:<br />  NODE* pNode;//ノードポインタ<br />  int Back;//階層戻し<br />  void Init();<br />  bool Load_Hierarchy(char* FileName); //階層メッシュ読み込み<br />  bool Load_Frame(FILE&amp; fp,NODE&amp; node,int&amp; hierarchy);  //フレーム読み込み<br />  bool Load_Animation(FILE&amp; fp);//アニメーション読み込み<br />  void Find_Frame(NODE&amp; node,char* name);//フレームを探す<br />  MATRIX Linear_Interpolation(MATRIX&amp; a,MATRIX&amp; b,float t);//線形補間<br />  vector&lt;OUTSIDEMATERIAL&gt; OutSide_Mat;//フレーム外マテリアル<br />  vector&lt;BONE&gt; Bone;//ボーン情報<br />  vector&lt;Vector3f&gt; Vertex;//頂点グループ<br />  vector&lt;Vector3f&gt; VertexView;//頂点グループ<br />  vector&lt;Vector3f&gt; Normal;//法線グループ<br />  vector&lt;int&gt; VertexIndex;//頂点インデックス<br />  vector&lt;int&gt; FaceIndex;//面インデックス<br />  vector&lt;int&gt; NormalIndex;//法線インデックス<br />  vector&lt;int&gt; MaterialIndex;//マテリアルインデックス<br />  vector&lt;UV&gt; uv;//UV<br />  void DataCreate(NODE&amp; node);<br />  void ViewDataCreate(NODE&amp; node);<br /> };<br /> //スキンメッシュクラス<br /> class SKINNEDMESH : public HIERARCHY{<br />  public:<br />   bool SkinnedMeshFlag;//スキンメッシュか階層メッシュか<br />   int AnimTicksPerSecond;//一秒間のコマ数<br />   bool Load_SkinnedMesh(char* FileName, float size);//スキンメッシュ読み込み<br />   SKINNEDMESH();<br />   SKINNEDMESH(char* FileName,float size);<br />   float Draw_Joint(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//ジョイント描画<br />   void Draw_Bone(MATRIX mat,float length);//ボーン描画<br />   void Calc_Bone(NODE&amp; node,int Frame_Time,MATRIX&amp; mat);//ボーン計算<br /> };<br /> SKINNEDMESH::SKINNEDMESH(){<br />  SkinnedMeshFlag=false;<br />  AnimTicksPerSecond=60;<br />  Size=1;<br />  Animation_MaxFrame=0;<br /> }<br /> SKINNEDMESH::SKINNEDMESH(char *FileName, float size){<br />  //階層メッシュアニメーションかスキンメッシュアニメーションかの判定<br />  char key[255];<br />  FILE* fp=NULL;<br />  SkinnedMeshFlag=false;<br />  AnimTicksPerSecond=60;<br />  Animation_MaxFrame=0;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  while(!feof(fp)){<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(fp,"%s ",key,sizeof(key));<br />   //テンプレート読み飛ばし<br />   if(strcmp(key,"template")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   if(strcmp(key,"AnimTicksPerSecond")==0){<br />    fgets(key,sizeof(key),fp);<br />    fscanf_s(fp,"%d;",&amp;AnimTicksPerSecond);<br />   }<br />   if((strcmp(key,"FrameTransformMatrix")==0)||(strcmp(key,"XSkinMeshHeader")==0)||<br />    (strcmp(key,"VertexDuplicationIndices")==0)||(strcmp(key,"SkinWeights")==0)){<br />     SkinnedMeshFlag=true;<br />   }<br />  }<br />  if(SkinnedMeshFlag){//スキンメッシュアニメーションなら<br />   Init();<br />   Size=size;<br />   Load_SkinnedMesh(FileName,size);<br />  }else{//階層メッシュアニメーションなら<br />  Init();<br />  Size=size;<br />  this-&gt;Load_Hierarchy(FileName);<br />  }<br /> }</p> <p>//データ作成<br /> void HIERARCHY::ViewDataCreate(NODE&amp; node){<br />  int Count=0;<br />     //マテリアル毎のデータを作成<br />     for(int i=0;i&lt;(signed)MaterialIndex.size();i++){<br />      if(FaceIndex[i]==3){<br />       for(int j=0;j&lt;3;j++){<br />        Tri.TriVer=VertexView[VertexIndex[Count+j]];<br />        Tri.TriNor=Normal[NormalIndex[Count+j]];<br />        //Tri.TriUV=uv[VertexIndex[Count+j]];<br />     Tri.TriView=VertexView[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Tridata[Count+j]=Tri;<br />       }<br />       Count+=3;<br />      }else{<br />       for(int j=0;j&lt;4;j++){<br />        Quad.QuadVer=Vertex[VertexIndex[Count+j]];<br />        Quad.QuadNor=Normal[NormalIndex[Count+j]];<br />        //Quad.QuadUV=uv[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Quaddata.push_back(Quad);<br />       }<br />       Count+=4;<br />      }<br />     }<br /> }<br /> //ボーン計算<br /> void SKINNEDMESH::Calc_Bone(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  MATRIX current=mat;<br />  while(1){<br />   if(node.Bone!=NULL){<br />    if(node.Anim.Key.size()==0){<br />     mat=mat.Multiplication(node.FrameTransformMatrix);<br />    }else{<br />     //線形補間<br />     for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />      int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />      int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />      float t=(float)Current/(float)Length;<br />      if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />       MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />       mat=mat.Multiplication(Linear);<br />      }<br />     }<br />    }<br />    for(int i=0;i&lt;(signed)Bone.size();i++){<br />     if(node.Bone-&gt;Bone_Name==Bone[i].Bone_Name)Bone[i].CurrentFrame=mat;<br />    }<br />   }<br />   //スキンメッシュアニメーションの具体的な処理↓(わかりやすくするため、あえてこのような記述にしてあります。)<br />   if(node.Mesh!=NULL){<br />    for(int i=0;i&lt;(signed)Vertex.size();i++){<br />     vec4d.x=Vertex[i].x;vec4d.y=Vertex[i].y;vec4d.z=Vertex[i].z;vec4d.w=1.0;<br />     Vector4f ret8=vec4d.GeometricTransform(Bone[3].bone_ofset);<br />     Vector4f ret7=ret8.GeometricTransform(Bone[3].CurrentFrame);<br />     Vector4f ret6=vec4d.GeometricTransform(Bone[2].bone_ofset);<br />     Vector4f ret5=ret6.GeometricTransform(Bone[2].CurrentFrame);<br />     Vector4f ret4=vec4d.GeometricTransform(Bone[1].bone_ofset);<br />     Vector4f ret3=ret4.GeometricTransform(Bone[1].CurrentFrame);<br />     Vector4f ret2=vec4d.GeometricTransform(Bone[0].bone_ofset);<br />     Vector4f ret=ret2.GeometricTransform(Bone[0].CurrentFrame);<br />     vec3d.x=ret.x*Bone[0].SkinWeights[i]+ret3.x*Bone[1].SkinWeights[i]+ret5.x*Bone[2].SkinWeights[i]+ret7.x*Bone[3].SkinWeights[i];<br />     vec3d.y=ret.y*Bone[0].SkinWeights[i]+ret3.y*Bone[1].SkinWeights[i]+ret5.y*Bone[2].SkinWeights[i]+ret7.y*Bone[3].SkinWeights[i];<br />     vec3d.z=ret.z*Bone[0].SkinWeights[i]+ret3.z*Bone[1].SkinWeights[i]+ret5.z*Bone[2].SkinWeights[i]+ret7.z*Bone[3].SkinWeights[i];<br />     VertexView[i]=vec3d;<br />    }<br />    ViewDataCreate(node);<br />   }<br />   if(node.Node!=NULL)Calc_Bone(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)Calc_Bone(*node.Next,Frame_Time,current);<br />   return;<br />  }<br />  return;<br /> }<br /> //ボーン描画<br /> void SKINNEDMESH::Draw_Bone(MATRIX mat,float length){<br />  glColor4f(0.0f,1.0f,1.0f,1.0f);<br />  glPushMatrix();<br />  glMultMatrixf(&amp;mat.mat_16[0]);<br />  glRotatef(90.0f,1.0f,0.0f,0.0f);<br />  if(mat._41+mat._42+mat._43!=0){<br />   if(length!=0)glutSolidCone(10.0f*Size, length, 4, 1);<br />  }<br />  glPopMatrix();<br /> }<br /> //ジョイント描画<br /> float SKINNEDMESH::Draw_Joint(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);<br />  glEnable(GL_COLOR_MATERIAL);<br />  MATRIX current=mat;<br />  MATRIX ret;<br />  float length=0;<br />  while(1){<br />   if(node.Bone!=NULL){<br />    glPushMatrix();<br />    if(node.Anim.Key.size()==0){<br />     mat=mat.Multiplication(node.FrameTransformMatrix);<br />    }else{<br />     //線形補間<br />     for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />      int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />      int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />      float t=(float)Current/(float)Length;<br />      if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />       MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />       mat=mat.Multiplication(Linear);<br />      }<br />     }<br />    }<br />    glMultMatrixf(&amp;mat.mat_16[0]);<br />    glColor4f(1.0f,1.0f,0.0f,1.0f);<br />    glutSolidSphere(5.0*Size,8,8);<br />    ret=mat;<br />    length=-sqrt((current._41-mat._41)*(current._41-mat._41)+(current._42-mat._42)*(current._42-mat._42)+(current._43-mat._43)*(current._43-mat._43));<br />    glPopMatrix();<br />   }</p> <p>  float len=0;<br />   if(node.Node!=NULL)len=Draw_Joint(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)len=Draw_Joint(*node.Next,Frame_Time,current);<br />   Draw_Bone(ret,len);<br />   return length;<br />  }<br />  glDisable(GL_COLOR_MATERIAL);<br />  return 0;<br /> }</p> <p><br /> bool SKINNEDMESH::Load_SkinnedMesh(char *FileName, float size){<br />  //Xファイルを開いて内容を読み込む<br />  Back=-1;<br />  int Hierarchy=0;<br />  FILE* fp=NULL;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  Load_Frame(*fp,Root,Hierarchy);<br />  //ボーン情報をセット<br />  for(int i=0;i&lt;(signed)Bone.size();i++){<br />   Find_Frame(Root,(char*)Bone[i].Bone_Name.c_str());<br />   pNode-&gt;Bone=&amp;Bone[i];<br />  }<br />  fseek(fp,0,SEEK_SET);<br />  this-&gt;Load_Animation(*fp);<br />  fclose(fp);</p> <p> return true;<br /> }</p> <p>//コンストラクタ<br /> HIERARCHY::HIERARCHY(){<br />  Init();<br /> }<br /> //コンストラクタ<br /> HIERARCHY::HIERARCHY(char* FileName,float size){<br />  Init();<br />  Size=size;<br />  Animation_MaxFrame=0;<br />  Load_Hierarchy(FileName);<br /> }<br /> //初期化<br /> void HIERARCHY::Init(){<br />  Root.Node=NULL;<br />  Root.Next=NULL;<br />  Root.FrameName="Root";<br />  Root.Mesh=NULL;<br />  Root.Bone=NULL;<br /> }</p> <p>//球面線形補間<br /> QUATERNION HIERARCHY::Spherical_Linear_Interpolation( QUATERNION&amp; q1, QUATERNION&amp; q2, float t)<br /> {<br />   QUATERNION q;<br />     if((q1.w==q2.w)&amp;&amp;(q1.x==q2.x)&amp;&amp;(q1.y==q2.y)&amp;&amp;(q1.z==q2.z)){<br />    for(int i=0;i&lt;4;i++){<br />     q.Index[i] = q1.Index[i];<br />    }<br />    return q;<br />   }<br />   float qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;<br />   float ss = 1.0f - qr * qr;<br />  <br />   if (ss == 0.0f) {<br />    for(int i=0;i&lt;4;i++){<br />     q.Index[i] = q1.Index[i];<br />    }<br />    return q;<br />   }else{<br />     float sp = sqrt(ss);<br />     float ph = acos(qr);<br />     float pt = ph * t;<br />     float t1 = sin(pt) / sp;<br />     float t0 = sin(ph - pt) / sp;</p> <p> for(int i=0;i&lt;4;i++){<br />   q.Index[i] = (q1.Index[i] * t0 + q2.Index[i] * t1);<br />  }<br />  return q;<br />   }<br /> }</p> <p>//線形補間<br /> MATRIX HIERARCHY::Linear_Interpolation(MATRIX&amp; a,MATRIX&amp; b,float t){<br />  MATRIX ret,r1,r2,r3;<br />  QUATERNION q1,q2,q3;<br />  Vector3f vec_A, vec_B, vec_R;<br />  //平行移動<br />  vec_A.x=a._41;<br />  vec_A.y=a._42;<br />  vec_A.z=a._43;<br />  vec_B.x=b._41;<br />  vec_B.y=b._42;<br />  vec_B.z=b._43;<br />  vec_R=vec_A*(1.0f-t) + vec_B*t;<br />  ret._41=vec_R.x;<br />  ret._42=vec_R.y;<br />  ret._43=vec_R.z;<br />  //スケーリング成分抜き出し<br />  vec_A.x=sqrt(a._11*a._11+a._21*a._21+a._31*a._31);<br />  vec_A.y=sqrt(a._12*a._12+a._22*a._22+a._32*a._32);<br />  vec_A.z=sqrt(a._13*a._13+a._23*a._23+a._33*a._33);<br />  vec_B.x=sqrt(b._11*b._11+b._21*b._21+b._31*b._31);<br />  vec_B.y=sqrt(b._12*b._12+b._22*b._22+b._32*b._32);<br />  vec_B.z=sqrt(b._13*b._13+b._23*b._23+b._33*b._33);<br />  <br />  for(int i=0;i&lt;4;i++){<br />   for(int j=0;j&lt;4;j++){<br />    r1.mat_4x4[j][i]=a.mat_4x4[j][i];<br />    r2.mat_4x4[j][i]=b.mat_4x4[j][i];<br />    if(i==0){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.x;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.x;}}<br />    if(i==1){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.y;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.y;}}<br />    if(i==2){if(j&lt;3){r1.mat_4x4[j][i]=a.mat_4x4[j][i]/vec_A.z;r2.mat_4x4[j][i]=b.mat_4x4[j][i]/vec_B.z;}}<br />   }<br />  }<br />  <br />  //クォータニオンを補間<br />  q1=r1.ToQuaternion();<br />  q2=r2.ToQuaternion();<br />  q3=Spherical_Linear_Interpolation(q1,q2,t);<br />  r3=q3.ToMatrix();<br />  <br />  vec_R=vec_A*(1.0f-t) + vec_B*t;<br />  ret._11=r3._11*vec_R.x;<br />  ret._21=r3._21*vec_R.x;<br />  ret._31=r3._31*vec_R.x;<br />  ret._12=r3._12*vec_R.y;<br />  ret._22=r3._22*vec_R.y;<br />  ret._32=r3._32*vec_R.y;<br />  ret._13=r3._13*vec_R.z;<br />  ret._23=r3._23*vec_R.z;<br />  ret._33=r3._33*vec_R.z;</p> <p> return ret;<br /> }<br /> //フレーム描画<br /> void HIERARCHY::Draw_Frame(NODE&amp; node,int Frame_Time,MATRIX&amp; mat){<br />  MATRIX current=mat;<br />  while(1){<br />   if(node.Mesh!=NULL){<br />    glEnableClientState(GL_VERTEX_ARRAY);<br />    glEnableClientState(GL_NORMAL_ARRAY);<br />    glPushMatrix();<br />    glMultMatrixf(&amp;mat.mat_16[0]);<br />    //線形補間<br />    for(int k=1;k&lt;(signed)node.Anim.Key.size();k++){<br />     int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ<br />     int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置<br />     float t=(float)Current/(float)Length;<br />     if((node.Anim.Key[k-1]&lt;=Frame_Time)&amp;&amp;(node.Anim.Key[k]&gt;Frame_Time)){<br />      MATRIX Linear = Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);<br />      mat=mat.Multiplication(Linear);<br />      glMultMatrixf(&amp;Linear.mat_16[0]);<br />     }<br />    }<br />    for(int i=0;i&lt;(signed)node.Mesh-&gt;Material.size();i++){<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.ambient);<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.diffuse);<br />     glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat *)&amp;node.Mesh-&gt;Material[i].MaterialColor.specular);<br />     glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,node.Mesh-&gt;Material[i].Shininess);</p> <p>    if(node.Mesh-&gt;Material[i].TexNo&gt;0){<br />      glEnableClientState(GL_TEXTURE_COORD_ARRAY);<br />      glEnable(GL_TEXTURE_2D);<br />      glBindTexture(GL_TEXTURE_2D, node.Mesh-&gt;TexID[node.Mesh-&gt;Material[i].TexNo-1]);<br />     }else{<br />      glDisable(GL_TEXTURE_2D);<br />      glDisableClientState(GL_TEXTURE_COORD_ARRAY);<br />     }<br />    <br />     if(node.Mesh-&gt;Material[i].Tridata.size()&gt;1){<br />      //glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &amp;node.Mesh-&gt;Material[i].Tridata[0].TriVer.x);<br />   glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &amp;node.Mesh-&gt;Material[i].Tridata[0].TriView.x);<br />      glNormalPointer(GL_FLOAT,sizeof(Tri),&amp;node.Mesh-&gt;Material[i].Tridata[0].TriNor.x);<br />      //if(node.Mesh-&gt;Material[i].TexNo&gt;0)glTexCoordPointer(2, GL_FLOAT, sizeof(Tri), &amp;node.Mesh-&gt;Material[i].Tridata[0].TriUV.u);<br />      glDrawArrays(GL_TRIANGLES,0,node.Mesh-&gt;Material[i].Tridata.size());<br />     }<br />     if(node.Mesh-&gt;Material[i].Quaddata.size()&gt;1){<br />      glVertexPointer(3, GL_FLOAT,sizeof(Quad) , &amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadVer.x);<br />      glNormalPointer(GL_FLOAT,sizeof(Quad),&amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadNor.x);<br />      //if(node.Mesh-&gt;Material[i].TexNo&gt;0)glTexCoordPointer(2, GL_FLOAT, sizeof(Quad), &amp;node.Mesh-&gt;Material[i].Quaddata[0].QuadUV.u);<br />      glDrawArrays(GL_QUADS,0,node.Mesh-&gt;Material[i].Quaddata.size());<br />     }<br />  <br />    }<br />    glDisableClientState(GL_VERTEX_ARRAY);<br />    glDisableClientState(GL_NORMAL_ARRAY);<br />    //glDisableClientState(GL_TEXTURE_COORD_ARRAY);<br />    //glDisable(GL_TEXTURE_2D);<br />    glPopMatrix();<br />   }</p> <p>  if(node.Node!=NULL)Draw_Frame(*node.Node,Frame_Time,mat);<br />   if(node.Next!=NULL)Draw_Frame(*node.Next,Frame_Time,current);<br />   if(node.Node==NULL)return;<br />   if(node.Next==NULL)return;<br />   return;<br />  }<br /> }<br /> //アニメーション描画<br /> void HIERARCHY::Animation_Draw(int Animation_NO,int Frame){<br />  MATRIX mat;<br />  Draw_Frame(Root,Frame,mat);<br /> }<br /> //描画<br /> void HIERARCHY::Draw(){<br />  MATRIX mat;<br />  Draw_Frame(Root,0,mat);<br /> }<br /> //フレームを探す<br /> void HIERARCHY::Find_Frame(NODE&amp; node,char* name){<br />  while(1){<br />   if(strcmp(node.FrameName.c_str(),name)==0){<br />    pNode=&amp;node;<br />    return;<br />   }<br />   if(node.Node!=NULL)Find_Frame(*node.Node,name);<br />   if(node.Next!=NULL)Find_Frame(*node.Next,name);<br />   if(node.Node==NULL)return;<br />   if(node.Next==NULL)return;<br />   return;<br />  }<br />  return;<br /> }<br /> //アニメーション読み込み<br /> bool HIERARCHY::Load_Animation(FILE&amp; fp){<br />  char buf[255];<br />  char name[255];<br />  char *next;<br />  int hierarchy=0,count=0,key=0,dummy=0,x=0,y=0,z=0,w=0;<br />  //合成行列<br />  MATRIX mix;</p> <p> //読み込み<br />  while(!feof(&amp;fp))<br />  {<br />   ZeroMemory(buf,sizeof(buf));<br />   fscanf_s(&amp;fp,"%s ",buf,sizeof(buf));<br />     //テンプレート読み飛ばし<br />   if(strcmp(buf,"template")==0){<br />    while(strcmp(buf,"}")){<br />     fscanf_s(&amp;fp,"%s ",buf,sizeof(buf));<br />    }<br />    continue;<br />   }<br />   //AnimationSetを探す<br />   if(strcmp(buf,"AnimationSet")==0){<br />     while(!feof(&amp;fp))<br />     {<br />      fgets(buf,sizeof(buf),&amp;fp);<br />      if((!strstr(buf,"Animation")==NULL)&amp;&amp;(strstr(buf,"Animation_")==NULL)){<br />       fgets(buf,sizeof(buf),&amp;fp);<br />       fgets(buf,sizeof(buf),&amp;fp);<br />       if((!strstr(buf,"{")==NULL)&amp;&amp;(!strstr(buf,"}")==NULL)){//名前の抽出<br />        sscanf_s(buf," { %s } ",&amp;name,sizeof(name));<br />        strtok_s( name, "}" ,&amp;next);<br />        pNode=NULL;<br />        Find_Frame(Root,name);<br />        while(!feof(&amp;fp)){<br />         fgets(buf,sizeof(buf),&amp;fp);<br />       if(!strstr(buf,"AnimationKey")==NULL){<br />        fgets(buf,sizeof(buf),&amp;fp);<br />        fgets(buf,sizeof(buf),&amp;fp);//キータイプ 4…行列タイプ]<br />        if(strstr(buf,"4;")==NULL)printf("対応していません");<br />        fgets(buf,sizeof(buf),&amp;fp);//キー数<br />        count=atoi(buf);<br />        for(int i=0;i&lt;count;i++){<br />         fscanf_s(&amp;fp,"%d;%d;",&amp;key,&amp;dummy);//キーの位置;データの数<br />         if((count-1==i)&amp;&amp;(Animation_MaxFrame&lt;key))Animation_MaxFrame=key;<br />         pNode-&gt;Anim.Key.push_back(key);<br />         if(dummy!=16)printf("対応していません");<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[0],&amp;mix.mat_16[1],&amp;mix.mat_16[2],&amp;mix.mat_16[3]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[4],&amp;mix.mat_16[5],&amp;mix.mat_16[6],&amp;mix.mat_16[7]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;mix.mat_16[8],&amp;mix.mat_16[9],&amp;mix.mat_16[10],&amp;mix.mat_16[11]);<br />         fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;mix.mat_16[12],&amp;mix.mat_16[13],&amp;mix.mat_16[14],&amp;mix.mat_16[15]);<br />         fgets(buf,sizeof(buf),&amp;fp);<br />         mix._41*=Size;<br />         mix._42*=Size;<br />         mix._43*=Size;<br />         pNode-&gt;Anim.Matrix.push_back(mix);<br />        }<br />        break;<br />       }<br />        }<br />       }<br />      }<br />     }<br />   }<br />  }<br />  return true;<br /> }<br /> //データ作成<br /> void HIERARCHY::DataCreate(NODE&amp; node){<br />  int Count=0;<br />     //マテリアル毎のデータを作成<br />     for(int i=0;i&lt;(signed)MaterialIndex.size();i++){<br />      if(FaceIndex[i]==3){<br />       for(int j=0;j&lt;3;j++){<br />        Tri.TriVer=Vertex[VertexIndex[Count+j]];<br />        Tri.TriNor=Normal[NormalIndex[Count+j]];<br />        //Tri.TriUV=uv[VertexIndex[Count+j]];<br />     Tri.TriView=Vertex[VertexIndex[Count+j]];<br />        if(MaterialIndex[i]&gt;=(signed)node.Mesh-&gt;Material.size()){<br />         mtl.MaterialName=this-&gt;OutSide_Mat[MaterialIndex[i]].MaterialName;<br />         mtl.MaterialColor=this-&gt;OutSide_Mat[MaterialIndex[i]].MaterialColor;<br />         mtl.Shininess=this-&gt;OutSide_Mat[MaterialIndex[i]].Shininess;<br />         node.Mesh-&gt;Material.push_back(mtl);<br />        }<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Tridata.push_back(Tri);<br />       }<br />       Count+=3;<br />      }else{<br />       for(int j=0;j&lt;4;j++){<br />        Quad.QuadVer=Vertex[VertexIndex[Count+j]];<br />        Quad.QuadNor=Normal[NormalIndex[Count+j]];<br />        //Quad.QuadUV=uv[VertexIndex[Count+j]];<br />        node.Mesh-&gt;Material[MaterialIndex[i]].Quaddata.push_back(Quad);<br />       }<br />       Count+=4;<br />      }<br />     }<br /> }<br /> //メッシュ読み込み<br /> bool HIERARCHY::Load_Mesh(FILE&amp; fp,NODE&amp; node){<br />  char key[255];<br />  char buf[255];<br />  int v1=0,v2=0,v3=0,v4=0;<br />  int Count=0,matCount=0,Hierarchy=1;<br />  string str="";<br />  fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />  node.Mesh=NULL;<br />  //読み込み<br />  while(!feof(&amp;fp))<br />  {<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />   //階層+<br />   if(strcmp(key,"{")==0){<br />    Hierarchy++;<br />   }<br />   //階層-<br />   if(strcmp(key,"}")==0){<br />    Hierarchy--;<br />    if(Hierarchy==0){<br />     if(node.Mesh!=NULL)DataCreate(node);<br />     return true;<br />    }<br />   }<br />  <br />   if(strcmp(key,"Frame")==0){<br />  if(node.Mesh!=NULL)DataCreate(node);<br />     return true;<br />   }<br />  <br />   //頂点 読み込み<br />   if(strcmp(key,"Mesh")==0)<br />   {<br />    node.Mesh =new MESH(msh);<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     fscanf_s(&amp;fp,"%f;%f;%f;,",&amp;vec3d.x,&amp;vec3d.y,&amp;vec3d.z);<br />     Vertex.push_back(vec3d*(float)Size);<br />  VertexView.push_back(vec3d*(float)Size);<br />    }<br />    //頂点インデックス読み込み<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&amp;fp);}//空行対策<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     int dammy=0;<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     str=buf;<br />     string::size_type first = str.find_first_not_of(' ');<br />  string::size_type tab = str.find_first_not_of('\t');<br />     string::size_type index = str.find("3;");<br />     if(index-first-tab==0){<br />      sscanf_s(buf,"%d;%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3);<br />      VertexIndex.push_back(v1);<br />      VertexIndex.push_back(v2);<br />      VertexIndex.push_back(v3);<br />     }<br />     if(!(index-first-tab==0)){<br />      sscanf_s(buf,"%d;%d,%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3,&amp;v4);<br />      VertexIndex.push_back(v1);<br />      VertexIndex.push_back(v2);<br />      VertexIndex.push_back(v3);<br />      VertexIndex.push_back(v4);<br />     }<br />     FaceIndex.push_back(dammy);<br />    }<br />   }</p> <p>  //法線 読み込み<br />   if(strcmp(key,"MeshNormals")==0)<br />   {<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     fscanf_s(&amp;fp,"%f;%f;%f;,",&amp;vec3d.x,&amp;vec3d.y,&amp;vec3d.z);<br />     Normal.push_back(vec3d);<br />    }<br />    //法線インデックス読み込み<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    fgets(buf,sizeof(buf),&amp;fp);<br />    while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&amp;fp);}//空行対策<br />    Count=atoi(buf); <br />    for(int i=0;i&lt;Count ;i++)<br />    {<br />     int dammy=0;<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     str=buf;<br />     string::size_type first = str.find_first_not_of(' ');<br />  string::size_type tab = str.find_first_not_of('\t');<br />     string::size_type index = str.find("3;");<br />     if(index-first-tab==0){<br />      sscanf_s(buf,"%d;%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3);<br />      NormalIndex.push_back(v1);<br />      NormalIndex.push_back(v2);<br />      NormalIndex.push_back(v3);<br />     }<br />     if(!(index-first-tab==0)){<br />      sscanf_s(buf,"%d;%d,%d,%d,%d;,",&amp;dammy,&amp;v1,&amp;v2,&amp;v3,&amp;v4);<br />      NormalIndex.push_back(v1);<br />      NormalIndex.push_back(v2);<br />      NormalIndex.push_back(v3);<br />      NormalIndex.push_back(v4);<br />     }<br />    }<br />   }</p> <p>  //マテリアルリスト<br />   if(strcmp(key,"MeshMaterialList")==0)<br />   {<br />    Hierarchy++;<br />    fgets(buf,sizeof(buf),&amp;fp);//空改行<br />    fgets(buf,sizeof(buf),&amp;fp);//マテリアル数<br />    matCount=atoi(buf);<br />    fgets(buf,sizeof(buf),&amp;fp);//リスト要素数<br />    Count=atoi(buf);<br />    for(int i=0;i&lt;Count;i++)<br />    {<br />     fgets(buf,sizeof(buf),&amp;fp);<br />     int test=atoi(buf);<br />     MaterialIndex.push_back(test);<br />    }<br />    char *next;<br />    for(int i=0;i&lt;matCount;i++)<br />    {<br />     fgets(buf,sizeof(buf),&amp;fp);<br />  sscanf_s(buf," { %s } ",&amp;buf,sizeof(buf));<br />  strtok_s( buf, "}" ,&amp;next);<br />  for(int j=0;j&lt;(signed)this-&gt;OutSide_Mat.size();j++){<br />   if(strcmp(this-&gt;OutSide_Mat[j].MaterialName.c_str(),buf)==0)node.MatNo.push_back(j);<br />  }<br />    }<br />   }<br />  }<br />  return false;<br /> }<br /> //フレーム読み込み<br /> bool HIERARCHY::Load_Frame(FILE&amp; fp,NODE&amp; node,int&amp; hierarchy){<br />  char key[255];<br />  char *next;<br />  int begin=0,end=0;<br />  int current=hierarchy;//現在の階層<br />  int file_pos;<br />  int count;<br />  int ID=0;<br />  float skinweights=0.0f;<br />  MATRIX dum;</p> <p> while(!feof(&amp;fp))<br />  {<br />   //キーワード 読み込み<br />   ZeroMemory(key,sizeof(key));<br />   fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />   //ヘッダー読み飛ばし<br />   if(strcmp(key,"Header")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   //テンプレート読み飛ばし<br />   if(strcmp(key,"template")==0){<br />    while(strcmp(key,"}")){<br />     fscanf_s(&amp;fp,"%s ",key,sizeof(key));<br />    }<br />    continue;<br />   }<br />   //階層+<br />   if(strcmp(key,"{")==0){<br />    begin++;<br />   }<br />   //階層-<br />   if(strcmp(key,"}")==0){<br />    end++;<br />   }<br />   //マテリアル読み込み<br />   if(strcmp(key,"Material")==0)<br />   {<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    strtok_s( key, "\n" ,&amp;next);<br />    outmtl.MaterialName=key;<br />    fgets(key,sizeof(key),&amp;fp);<br />    //ディフューズ<br />    fscanf_s(&amp;fp,"%f;%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z,&amp;vec4d.w);<br />    outmtl.MaterialColor.diffuse=(const Color4 &amp;)vec4d;<br />    //SHININESS<br />    fscanf_s(&amp;fp,"%f;",&amp;outmtl.Shininess);<br />    //スペキュラー<br />    fscanf_s(&amp;fp,"%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z);<br />    outmtl.MaterialColor.specular=(const Color4 &amp;)vec4d;<br />    //エミッシブ<br />    fscanf_s(&amp;fp,"%f;%f;%f;;",&amp;vec4d.x,&amp;vec4d.y,&amp;vec4d.z);<br />    outmtl.MaterialColor.ambient=(const Color4 &amp;)vec4d;</p> <p>   this-&gt;OutSide_Mat.push_back(outmtl);<br />   }<br />   //ボーン<br />   if(strcmp(key,"SkinWeights")==0){<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    sscanf_s(key,"\"%s\";",&amp;key,sizeof(key));<br />    strtok_s( key, "\"" ,&amp;next);<br />    bne.Bone_Name=key;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fgets(key,sizeof(key),&amp;fp);<br />    count=atoi(key);<br />    for(int i=0;i&lt;count;i++){<br />     fscanf_s(&amp;fp,"%d,",&amp;ID);<br />     bne.SkinID.push_back(ID);<br />    }<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    for(int i=0;i&lt;count;i++){<br />     fscanf_s(&amp;fp,"%f,",&amp;skinweights);<br />     bne.SkinWeights.push_back(skinweights);<br />    }<br />    fscanf_s(&amp;fp,"%s;",key,sizeof(key));<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[0],&amp;dum.mat_16[1],&amp;dum.mat_16[2],&amp;dum.mat_16[3]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[4],&amp;dum.mat_16[5],&amp;dum.mat_16[6],&amp;dum.mat_16[7]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[8],&amp;dum.mat_16[9],&amp;dum.mat_16[10],&amp;dum.mat_16[11]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;dum.mat_16[12],&amp;dum.mat_16[13],&amp;dum.mat_16[14],&amp;dum.mat_16[15]);<br />    bne.bone_ofset=dum;<br />    Bone.push_back(bne);<br />    bne.SkinID.clear();<br />    bne.SkinWeights.clear();<br />   }<br />   //親フレームからのトランスフォーム行列<br />   if(strcmp(key,"FrameTransformMatrix")==0){<br />    begin++;<br />    fgets(key,sizeof(key),&amp;fp);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[0],&amp;dum.mat_16[1],&amp;dum.mat_16[2],&amp;dum.mat_16[3]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[4],&amp;dum.mat_16[5],&amp;dum.mat_16[6],&amp;dum.mat_16[7]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f,",&amp;dum.mat_16[8],&amp;dum.mat_16[9],&amp;dum.mat_16[10],&amp;dum.mat_16[11]);<br />    fscanf_s(&amp;fp,"%f,%f,%f,%f;;",&amp;dum.mat_16[12],&amp;dum.mat_16[13],&amp;dum.mat_16[14],&amp;dum.mat_16[15]);<br />    node.FrameTransformMatrix=dum;<br />    node.FrameTransformMatrix._41*=Size;<br />    node.FrameTransformMatrix._42*=Size;<br />    node.FrameTransformMatrix._43*=Size;<br />   }<br />  <br />   //フレーム<br />   if(strcmp(key,"Frame")==0){<br />    fscanf_s(&amp;fp,"%s ",key,sizeof(key));</p> <p>   if(((begin==0)&amp;&amp;(end==0))||(end-begin==-1)){//子ノード追加<br />     node.Node=new NODE(nde);<br />     node.Node-&gt;FrameName=key;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Node);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     hierarchy++;<br />     Load_Frame(fp,*node.Node,hierarchy);//再帰呼び出し<br />    }</p> <p>   if(Back==current){//階層戻り先にきた場合、同一階層追加<br />     Back=-1;<br />     node.Next=new NODE(nde);<br />     node.Next-&gt;FrameName=buffer;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Next);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     Load_Frame(fp,*node.Next,current);//再帰呼び出し<br />    }<br />    if(end-begin&gt;0){//"}"が"{"より多い時は階層を戻る<br />     strcpy_s(buffer,255,key);<br />     Back=current-(end-begin);<br />     return true;<br />    }<br />  <br />    if((end-begin==0)&amp;&amp;((begin!=0)&amp;&amp;(end!=0))){//同一階層追加<br />     node.Next=new NODE(nde);<br />     node.Next-&gt;FrameName=key;<br />     file_pos=ftell(&amp;fp);<br />     Load_Mesh(fp,*node.Next);<br />     fseek( &amp;fp, file_pos, SEEK_SET );<br />     Load_Frame(fp,*node.Next,current);//再帰呼び出し<br />    }<br />    //階層を戻る<br />    if((Back!=-1)&amp;&amp;(Back&lt;current))return true;<br />   }<br />  }<br />  return true;<br /> }<br /> //階層メッシュ読み込み<br /> bool HIERARCHY::Load_Hierarchy(char* FileName){<br />  //Xファイルを開いて内容を読み込む<br />  Back=-1;<br />  int Hierarchy=0;<br />  FILE* fp=NULL;<br />  fopen_s(&amp;fp,FileName,"rt");<br />  //読み込み<br />  fseek(fp,0,SEEK_SET);<br />  Load_Frame(*fp,Root,Hierarchy);<br />  fseek(fp,0,SEEK_SET);<br />  Load_Animation(*fp);<br />  fclose(fp);<br />  return true;<br /> }</p> </td> </tr></tbody></table><div> </div> <div>main.cpp</div> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #include &lt;GL/freeglut/freeglut.h&gt;<br /> #include "xfile.h"<br /> #include "font.h"</p> <p>#define WIDTH 640<br /> #define HEIGHT 480</p> <p>float angle=100.0f;<br /> SKINNEDMESH* SkinMesh;</p> <p>GLFONT *font;<br /> wstring wstr;<br /> wchar_t wchar[255];<br /> int CurrentFrame;<br /> MATRIX mat;</p> <p>void display(void)<br /> {<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  glViewport(0,0,WIDTH,HEIGHT);<br />  glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  gluPerspective(30.0, WIDTH/HEIGHT, 0.1, 5000.0);<br />  glMatrixMode(GL_MODELVIEW);<br />  glLoadIdentity();<br />  gluLookAt(-1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);</p> <p> glRotatef(angle, 0.0f, 1.0f, 0.0f);<br />  SkinMesh-&gt;Calc_Bone(SkinMesh-&gt;Root,CurrentFrame,mat);<br />  glColor4f(1.0f,1.0f,1.0f,1.0f);</p> <p> glDisable(GL_LIGHTING);<br />  glDisable(GL_DEPTH_TEST);<br />  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);<br />  SkinMesh-&gt;Animation_Draw(0,CurrentFrame);<br />  SkinMesh-&gt;Draw_Joint(SkinMesh-&gt;Root,CurrentFrame,mat);<br />  glEnable(GL_DEPTH_TEST);<br />  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);<br />  glEnable(GL_LIGHTING);</p> <p> //SkinMesh-&gt;Animation_Draw(0,CurrentFrame);</p> <p> glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  glMatrixMode(GL_MODELVIEW);<br />  glLoadIdentity();<br />  glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);</p> <p> glColor4f(1.0f, 1.0f, 1.0f, 1.0f);<br />  wstr=L"最大フレーム[";<br />  _itow_s(SkinMesh-&gt;Animation_MaxFrame,wchar,255,10);<br />  wstr+=wchar;<br />  wstr+=L"]";<br />  font-&gt;DrawStringW(0,16,(wchar_t *)wstr.c_str());<br />  wstr=L"現在のフレーム[";<br />  _itow_s(CurrentFrame,wchar,255,10);<br />  wstr+=wchar;<br />  wstr+=L"]";<br />  font-&gt;DrawStringW(0,32,(wchar_t *)wstr.c_str());</p> <p> glutSwapBuffers();<br /> }<br /> void idle(void)<br /> {<br />  if(SkinMesh-&gt;Animation_MaxFrame&lt;CurrentFrame)CurrentFrame=0;<br />  Sleep(1);<br />  glutPostRedisplay();<br /> }<br /> //タイマー<br /> void timer(int value) {<br />  CurrentFrame+=30;<br />  glutTimerFunc(10 , timer , 0);<br /> }</p> <p>void Init(){<br />  glClearColor(0.0, 0.0, 0.0, 1.0);<br />  glEnable(GL_BLEND);<br />  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);<br />  glEnable(GL_DEPTH_TEST);<br />  glEnable(GL_LIGHT0);<br />  glEnable(GL_LIGHTING);<br />  glEnable(GL_CULL_FACE);<br />  glCullFace(GL_BACK);</p> <p> SkinMesh = new SKINNEDMESH("box.x",1.0f);<br />  font = new GLFONT(L"MS明朝", 16);</p> <p>}<br /> int main(int argc, char *argv[])<br /> {<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutCreateWindow("スキンメッシュアニメーション");<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  glutTimerFunc(100 , timer , 0);<br />  Init();<br />  glutMainLoop();<br />  return 0;<br /> }</p> </td> </tr></tbody></table><div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <div> </div> <p> </p>

表示オプション

横に並べて表示:
変化行の前後のみ表示: