再びキーフレーム

長らく道を逸れましたが、ここで再びキーフレームに戻ります。

.Xのアニメーションキーのキータイプ情報

0…回転  w,x,y,zの順にクォータニオンデータ
1…拡大縮小 x,y,zの順に拡大縮小データ
2…平行移動 x,y,zの順に平行移動データ
4…合成行列 回転、拡大縮小、平行移動行列が掛け合わされた4×4行列データ

まず、最初に知っておかなくてはならない事があります。
それは、当サイトで使用している Cyberdelia は、合成行列タイプの
アニメーションデータは階層構造が正しく生成できないという事です。
詳しくは Cyberdelia に付属のヘルプを参照して下さい。

とは言っても、合成行列でないタイプの方は正しく出力されますので、
それを元に合成行列を作成し、単純なキーフレームアニメーションを表示して
みたいと思います。

とりあえず、平行移動行列だけに対応したプログラムを作成しました。
今回もわかりやすくするために新しくsample2.xというファイルを作成し
それを表示しています。

font.h

class GLFONT
{
public:
 HFONT Hfont;
 HDC Hdc;
 GLFONT(wchar_t *fontname, int size);
 void DrawStringW(int x,int y,wchar_t *format, ...);
};
//コンストラクタ フォント作成
GLFONT::GLFONT(wchar_t *fontname, int size)
{
 Hfont = CreateFontW(
        size,      //フォント高さ
        0,       //文字幅
        0,       //テキストの角度
        0,       //ベースラインとx軸との角度
        FW_REGULAR,     //フォントの太さ
        FALSE,      //イタリック体
        FALSE,      //アンダーライン
        FALSE,      //打ち消し線
        SHIFTJIS_CHARSET,   //文字セット
        OUT_DEFAULT_PRECIS,   //出力精度
        CLIP_DEFAULT_PRECIS,  //クリッピング精度
        ANTIALIASED_QUALITY,  //出力品質
        FIXED_PITCH | FF_MODERN, //ピッチとファミリー
        fontname);     //書体名

 Hdc = wglGetCurrentDC();
 SelectObject(Hdc, Hfont);
}
//ワイド文字列の描画
void GLFONT::DrawStringW(int x,int y,wchar_t *format, ...)
{
 wchar_t buf[256];
 va_list ap;
 int Length=0;
 int list=0;
 
 //ポインタがNULLの場合は終了
 if ( format == NULL )
  return;

 //文字列変換
 va_start(ap, format);
 vswprintf_s(buf, format, ap);
 va_end(ap);

 Length = wcslen(buf);
 list = glGenLists(Length);
 for( int i=0; i  wglUseFontBitmapsW(Hdc, buf[i], 1, list + (DWORD)i);
 }

 glDisable(GL_LIGHTING);
 glRasterPos2i(x, y);
 //ディスプレイリストで描画
 for( int i=0; i {
  glCallList(list + i);
 }
 glEnable(GL_LIGHTING);
 //ディスプレイリスト破棄
 glDeleteLists(list, Length);
 list = 0;
 Length = 0;
}

PNG.h

#pragma once
#include "lodepng.h"

//テクスチャクラス
class TEXTURE{
protected:
 LodePNG_Decoder decoder;//デコーダ
 unsigned char* buffer;//バッファ
 size_t buffersize, imagesize;//サイズ
public:
 TEXTURE();
 TEXTURE(const char* FileName);//コンストラクタ
 void LOAD_PNG(const char* FileName);//PNG読み込み
 unsigned char* image;//イメージポインタ
 unsigned int Width,Height;//画像サイズ
};
TEXTURE::TEXTURE(){
}
TEXTURE::TEXTURE(const char* FileName){
 LOAD_PNG(FileName);
}
void TEXTURE::LOAD_PNG(const char* FileName){
 LodePNG_Decoder_init(&decoder);
 //ロード
 LodePNG_loadFile(&buffer, &buffersize, FileName);
 //デコード
 LodePNG_decode(&decoder, &image, &imagesize, buffer, buffersize);
 //幅,高さ
 Width = decoder.infoPng.width;Height = decoder.infoPng.height;
}

 xfile.h

#pragma once
#include "PNG.h"

using namespace std;
//3つのベクトル
struct Vector3f{
 float x;
 float y;
 float z;
}vec3d;
Vector3f & operator*(Vector3f &v,float size){
 v.x *= size;
 v.y *= size;
 v.z *= size;
 return v;
}
//4つのベクトル
struct Vector4f{
 float x;
 float y;
 float z;
 float w;
}vec4d;
//4つのカラー
struct Color4{
 float r;
 float g;
 float b;
 float a;
};
//4つの反射
struct Reflection4{
 Color4 diffuse;
 Color4 ambient;
 Color4 emission;
 Color4 specular;
};
//UV座標
struct UV{
 float u;//u値
 float v;//v値
}vec2d;
//ポリゴンデータ
struct Triangle{
 Vector3f TriVer;
 Vector3f TriNor;
 UV TriUV;
}Tri;
//ポリゴンデータ
struct Quadrangle{
 Vector3f QuadVer;
 Vector3f QuadNor;
 UV QuadUV;
}Quad;
//マテリアル構造体
struct MATERIAL{
 string MaterialName;//マテリアル名
 Reflection4 MaterialColor;//反射
 float Shininess;//shininess
 string TextureName;//テクスチャ名
 int TexNo;//テクスチャNO.
 vector Tridata;//三角面データ
 vector Quaddata;//四角面データ
}mtl;
//メッシュ構造体
struct MESH{
public:
 vector Material;//マテリアル
 vector TexData;//テクスチャデータ
 vector TexID;//テクスチャID
 GLuint TexID2;//代入用
 TEXTURE* tex;//代入用
}msh;
//アニメーションデータ構造体
struct ANIMATION{
public:
 vector Key;//アニメーションキー
 vector > Matrix;//行列データ
}anm;
//ノード構造体
struct NODE{
 NODE* Node;//子ノード
 NODE* Next;//隣の階層
 string FrameName;//フレーム名
 MESH* Mesh;//メッシュ
 ANIMATION Anim;//アニメーションデータ
}nde;
//階層メッシュクラス
class HIERARCHY{
public:
 bool Load_Hierarchy(char* FileName); //階層メッシュ読み込み
 bool Load_Frame(FILE& fp,NODE& node,int& hierarchy);  //フレーム読み込み
 bool Load_Mesh(FILE& fp,NODE& node);//メッシュ読み込み
 bool Load_Animation(FILE& fp);//アニメーション読み込み
 void Find_Frame(NODE& node,char* name);//フレームを探す
 void Draw();//描画
 void Draw_Frame(NODE& node,int Frame_Time);
 void Animation_Draw(int Animation_NO,int Frame);
 void Init();
 HIERARCHY();
 HIERARCHY(char* FileName,int size);
 NODE Root;//ルートノード
 int Size;//サイズ
 int Back;//階層戻し
 char buffer[255];
 NODE* pNode;//ノードポインタ
 int Animation_MaxFrame;
};
HIERARCHY::HIERARCHY(){
 Init();
}
HIERARCHY::HIERARCHY(char* FileName,int size){
 Init();
 Size=size;
 Load_Hierarchy(FileName);
}
void HIERARCHY::Init(){
 Root.Node=NULL;
 Root.Next=NULL;
 Root.FrameName="Root";
 Root.Mesh=NULL;
}
void HIERARCHY::Draw_Frame(NODE& node,int Frame_Time){
 while(1){
  if(node.Mesh!=NULL){
   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_NORMAL_ARRAY);
   for(int i=0;i<(signed)node.Mesh->Material.size();i++){
    glPushMatrix();
    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(const GLfloat *)&node.Mesh->Material[i].MaterialColor.ambient);
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(const GLfloat *)&node.Mesh->Material[i].MaterialColor.diffuse);
    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat *)&node.Mesh->Material[i].MaterialColor.specular);
    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,node.Mesh->Material[i].Shininess);

    if(node.Mesh->Material[i].TexNo>0){
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glEnable(GL_TEXTURE_2D);
     glBindTexture(GL_TEXTURE_2D, node.Mesh->TexID[node.Mesh->Material[i].TexNo-1]);
    }else{
     glDisable(GL_TEXTURE_2D);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

    //とりあえずパラパラアニメ
    for(int k=1;k<(signed)node.Anim.Key.size()-1;k++){
     if((node.Anim.Key[k-1]<=Frame_Time)&&(node.Anim.Key[k]>Frame_Time)){
      glMultMatrixf(&node.Anim.Matrix[k-1][0]);
     }
    }
    if(node.Mesh->Material[i].Tridata.size()>1){
     glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &node.Mesh->Material[i].Tridata[0].TriVer.x);
     glNormalPointer(GL_FLOAT,sizeof(Tri),&node.Mesh->Material[i].Tridata[0].TriNor.x);
     //if(node.Mesh->Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Tri), &node.Mesh->Material[i].Tridata[0].TriUV.u);
     glDrawArrays(GL_TRIANGLES,0,node.Mesh->Material[i].Tridata.size());
    }
    if(node.Mesh->Material[i].Quaddata.size()>1){
     glVertexPointer(3, GL_FLOAT,sizeof(Quad) , &node.Mesh->Material[i].Quaddata[0].QuadVer.x);
     glNormalPointer(GL_FLOAT,sizeof(Quad),&node.Mesh->Material[i].Quaddata[0].QuadNor.x);
     //if(node.Mesh->Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Quad), &node.Mesh->Material[i].Quaddata[0].QuadUV.u);
     glDrawArrays(GL_QUADS,0,node.Mesh->Material[i].Quaddata.size());
    }
    glPopMatrix();
 
   }
   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_NORMAL_ARRAY);
   //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   //glDisable(GL_TEXTURE_2D);
  }

  if(node.Node!=NULL)Draw_Frame(*node.Node,Frame_Time);
  if(node.Next!=NULL)Draw_Frame(*node.Next,Frame_Time);
  if(node.Node==NULL)return;
  if(node.Next==NULL)return;
  return;
 }
}
void HIERARCHY::Animation_Draw(int Animation_NO,int Frame){
 Draw_Frame(Root,Frame);
}
void HIERARCHY::Draw(){
 Draw_Frame(Root,0);
}
//フレームを探す
void HIERARCHY::Find_Frame(NODE& node,char* name){
  while(1){
   if(strcmp(node.FrameName.c_str(),name)==0){
    pNode=&node;
    return;
   }
   if(node.Node!=NULL)Find_Frame(*node.Node,name);
   if(node.Next!=NULL)Find_Frame(*node.Next,name);
   if(node.Node==NULL)return;
   if(node.Next==NULL)return;
   return;
  }
 return;
}
//アニメーション読み込み
bool HIERARCHY::Load_Animation(FILE& fp){
 char buf[255];
 char name[255];
 vector Quaternion;
 vector Transform;
 vector Scaling;
 vector Key1;
 vector Key2;
 vector Key3;
 int hierarchy=0,count=0,keyID,key=0,dummy=0,x=0,y=0,z=0,w=0;
 //平行移動用
 GLfloat move[]={
  1,0,0,0,
  0,1,0,0,
  0,0,1,0,
  0,0,0,1
 };

 //読み込み
 while(!feof(&fp))
 {
  ZeroMemory(buf,sizeof(buf));
  fscanf_s(&fp,"%s ",buf,sizeof(buf));
  //AnimationSetを探す
  if(strcmp(buf,"AnimationSet")==0){
    while(!feof(&fp))
    {
     fgets(buf,sizeof(buf),&fp);
     if(strstr(buf,"AnimationKey")==NULL){
      if((!strstr(buf,"{")==NULL)&&(!strstr(buf,"}")==NULL)){//名前の抽出
       sscanf_s(buf," { %s } ",&name,sizeof(name));
       pNode=NULL;
       Find_Frame(Root,name);
       pNode->Anim.Matrix.resize(Key3.size());
       for(int i=0;i<(signed)Key3.size();i++){
        move[12]=Transform[i].x*Size;
        move[13]=Transform[i].y*Size;
        move[14]=Transform[i].z*Size;
        pNode->Anim.Key.push_back(Key3[i]);
        pNode->Anim.Matrix[i].resize(16);
        for(int j=0;j<16;j++)pNode->Anim.Matrix[i][j]=move[j];
       }
       Animation_MaxFrame=Key3[Key3.size()-1];
       Quaternion.clear();
       Scaling.clear();
       Transform.clear();
       Key1.clear();
       Key2.clear();
       Key3.clear();
      }
     }else{
    fgets(buf,sizeof(buf),&fp);//キー 0 回転 , 1 拡大縮小 , 2 平行移動
    keyID=atoi(buf);
    fgets(buf,sizeof(buf),&fp);//キーデータの個数
    count=atoi(buf);
    switch (keyID){
     case 0:
      for(int i=0;i
       fscanf_s(&fp,"%d;%d;%f,%f,%f,%f;;,",&key,&dummy,&vec4d.w,&vec4d.x,&vec4d.y,&vec4d.z);
       Key1.push_back(key);
       Quaternion.push_back(vec4d);
      }
      break;
     case 1:
      for(int i=0;i
       fscanf_s(&fp,"%d;%d;%f,%f,%f;;,",&key,&dummy,&vec3d.x,&vec3d.y,&vec3d.z);
       Key2.push_back(key);
       Scaling.push_back(vec3d);
      }
      break;
     case 2:
      for(int i=0;i
       fscanf_s(&fp,"%d;%d;%f,%f,%f;;,",&key,&dummy,&vec3d.x,&vec3d.y,&vec3d.z);
       Key3.push_back(key);
       Transform.push_back(vec3d);
      }
      break;
     default:
      break;
    }
     }
    }
  }
 }
 Animation_MaxFrame=pNode->Anim.Key[pNode->Anim.Key.size()-1];
 Quaternion.clear();
 Scaling.clear();
 Transform.clear();
 Key1.clear();
 Key2.clear();
 Key3.clear();
 return true;
}
//メッシュ読み込み
bool HIERARCHY::Load_Mesh(FILE& fp,NODE& node){
 vector Vertex;//頂点
 vector Normal;//法線
 vector uv;//UV
 vector VertexIndex;
 vector NormalIndex;
 vector MaterialIndex;
 vector FaceIndex;

 char key[255];
 char buf[255];
 
 int v1=0,v2=0,v3=0,v4=0;
 int Count=0;
 string str="";

 //読み込み
 while(!feof(&fp))
 {
  //キーワード 読み込み
  ZeroMemory(key,sizeof(key));
  fscanf_s(&fp,"%s ",key,sizeof(key));
  //頂点 読み込み
  if(strcmp(key,"Mesh")==0)
  {
   fgets(buf,sizeof(buf),&fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),&fp);
   Count=atoi(buf);
   for(int i=0;i   {
    fscanf_s(&fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
    Vertex.push_back(vec3d*(float)Size);
   }
   //頂点インデックス読み込み 
   fgets(buf,sizeof(buf),&fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),&fp);
   while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&fp);}//空行対策
   Count=atoi(buf);  
   for(int i=0;i   {
    int dammy=0;
    fgets(buf,sizeof(buf),&fp);
    str=buf;
    string::size_type first = str.find_first_not_of(" ");
    string::size_type index = str.find("3;");
    if(index-first==0){
     sscanf_s(buf,"%d;%d,%d,%d;,",&dammy,&v1,&v2,&v3);
     VertexIndex.push_back(v1);
     VertexIndex.push_back(v2);
     VertexIndex.push_back(v3);
    }
    if((index==-1)||(index-first>1)){
     sscanf_s(buf,"%d;%d,%d,%d,%d;,",&dammy,&v1,&v2,&v3,&v4);
     VertexIndex.push_back(v1);
     VertexIndex.push_back(v2);
     VertexIndex.push_back(v3);
     VertexIndex.push_back(v4);
    }
    FaceIndex.push_back(dammy);
   }
  }

  //法線 読み込み
  if(strcmp(key,"MeshNormals")==0)
  {
   fgets(buf,sizeof(buf),&fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),&fp);
   Count=atoi(buf);
   for(int i=0;i   {
    fscanf_s(&fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
    Normal.push_back(vec3d);
   }
   //法線インデックス読み込み 
   fgets(buf,sizeof(buf),&fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),&fp);
   while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&fp);}//空行対策
   Count=atoi(buf);  
   for(int i=0;i   {
    int dammy=0;
    fgets(buf,sizeof(buf),&fp);
    str=buf;
    string::size_type first = str.find_first_not_of(" ");
    string::size_type index = str.find("3;");
    if(index-first==0){
     sscanf_s(buf,"%d;%d,%d,%d;,",&dammy,&v1,&v2,&v3);
     NormalIndex.push_back(v1);
     NormalIndex.push_back(v2);
     NormalIndex.push_back(v3);
    }
    if((index==-1)||(index-first>1)){
     sscanf_s(buf,"%d;%d,%d,%d,%d;,",&dammy,&v1,&v2,&v3,&v4);
     NormalIndex.push_back(v1);
     NormalIndex.push_back(v2);
     NormalIndex.push_back(v3);
     NormalIndex.push_back(v4);
    }
   }
  }

  //マテリアルリスト
  if(strcmp(key,"MeshMaterialList")==0)
  {
   fgets(buf,sizeof(buf),&fp);//空改行
   fgets(buf,sizeof(buf),&fp);//マテリアル数
   fgets(buf,sizeof(buf),&fp);//リスト要素数
   Count=atoi(buf);
   for(int i=0;i
   {
    fgets(buf,sizeof(buf),&fp);
    int test=atoi(buf);
    MaterialIndex.push_back(test);
   }
  }
  //マテリアル読み込み
  if(strcmp(key,"Material")==0)
  {
   fgets(buf,sizeof(buf),&fp);//直後の行にあると推定 改行する
   //ディフューズ
   fscanf_s(&fp,"%f;%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z,&vec4d.w);
   mtl.MaterialColor.diffuse=(const Color4 &)vec4d;
   //SHININESS 
   fscanf_s(&fp,"%f;",&mtl.Shininess);
   //スペキュラー
   fscanf_s(&fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
   mtl.MaterialColor.specular=(const Color4 &)vec4d;
   //エミッシブ
   fscanf_s(&fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
   mtl.MaterialColor.ambient=(const Color4 &)vec4d;

   node.Mesh =new MESH(msh);
   node.Mesh->Material.push_back(mtl);
 Count=0;
 //マテリアル毎のデータを作成
 for(int i=0;i<(signed)MaterialIndex.size();i++){
  if(FaceIndex[i]==3){
   for(int j=0;j<3;j++){
    Tri.TriVer=Vertex[VertexIndex[Count+j]];
    Tri.TriNor=Normal[NormalIndex[Count+j]];
    //Tri.TriUV=uv[VertexIndex[Count+j]];
    node.Mesh->Material[MaterialIndex[i]].Tridata.push_back(Tri);
   }
   Count+=3;
  }else{
   for(int j=0;j<4;j++){
    Quad.QuadVer=Vertex[VertexIndex[Count+j]];
    Quad.QuadNor=Normal[NormalIndex[Count+j]];
    //Quad.QuadUV=uv[VertexIndex[Count+j]];
 node.Mesh->Material[MaterialIndex[i]].Quaddata.push_back(Quad);
   }
   Count+=4;
  }
 }
 Vertex.clear();
 Normal.clear();
 uv.clear();
 VertexIndex.clear();
 NormalIndex.clear();
 MaterialIndex.clear();
 FaceIndex.clear();
 return true;
 }
 }
 return false;
}
//フレーム読み込み
bool HIERARCHY::Load_Frame(FILE& fp,NODE& node,int& hierarchy){
 char key[255];
 int begin=0,end=0;
 int current=hierarchy;//現在の階層
 int file_pos;

 while(!feof(&fp))
 {
  //キーワード 読み込み
  ZeroMemory(key,sizeof(key));
  fscanf_s(&fp,"%s ",key,sizeof(key));
  //ヘッダー読み飛ばし
  if(strcmp(key,"Header")==0){
   while(strcmp(key,"}")){
    fscanf_s(&fp,"%s ",key,sizeof(key));
   }
   continue;
  }
  //テンプレート読み飛ばし
  if(strcmp(key,"template")==0){
   while(strcmp(key,"}")){
    fscanf_s(&fp,"%s ",key,sizeof(key));
   }
   continue;
  }
  //階層+
  if(strcmp(key,"{")==0){
   begin++;
  }
  //階層-
  if(strcmp(key,"}")==0){
   end++;
  }
  //フレーム
  if(strcmp(key,"Frame")==0){
   fscanf_s(&fp,"%s ",key,sizeof(key));

   if(((begin==0)&&(end==0))||(end-begin==-1)){//子ノード追加
    node.Node=new NODE(nde);
    node.Node->FrameName=key;
    file_pos=ftell(&fp);
    Load_Mesh(fp,*node.Node);
    fseek( &fp, file_pos, SEEK_SET );
    hierarchy++;
    Load_Frame(fp,*node.Node,hierarchy);//再帰呼び出し
   }

   if(Back==current){//階層戻り先にきた場合、同一階層追加
    Back=-1;
    node.Next=new NODE(nde);
    node.Next->FrameName=buffer;
    file_pos=ftell(&fp);
    Load_Mesh(fp,*node.Next);
    fseek( &fp, file_pos, SEEK_SET );
    Load_Frame(fp,*node.Next,current);//再帰呼び出し
   }
   if(end-begin>0){//"}"が"{"より多い時は階層を戻る
    strcpy_s(buffer,255,key);
    Back=current-(end-begin);
    return true;
   }
 
   if((end-begin==0)&&((begin!=0)&&(end!=0))){//同一階層追加
    node.Next=new NODE(nde);
    node.Next->FrameName=key;
    file_pos=ftell(&fp);
    Load_Mesh(fp,*node.Next);
    fseek( &fp, file_pos, SEEK_SET );
    Load_Frame(fp,*node.Next,current);//再帰呼び出し
   }
   //階層を戻る
   if((Back!=-1)&&(Back  }
 }
 return true;
}
//階層メッシュ読み込み
bool HIERARCHY::Load_Hierarchy(char* FileName){
 //Xファイルを開いて内容を読み込む
 Back=-1;
 int Hierarchy=0;
 FILE* fp=NULL;
 fopen_s(&fp,FileName,"rt");
 //読み込み
 fseek(fp,0,SEEK_SET);
 Load_Frame(*fp,Root,Hierarchy);
 fseek(fp,0,SEEK_SET);
 Load_Animation(*fp);
 fclose(fp);
 return true;
}

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#include <GL/freeglut/freeglut.h>
#include "xfile.h"
#include "font.h"

#define WIDTH 320
#define HEIGHT 240

float angle=0.0f;
HIERARCHY* hierarchy;

GLFONT *font;
wstring wstr;
wchar_t wchar[255];
int CurrentFrame;


void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glViewport(0,0,WIDTH,HEIGHT);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(30.0, WIDTH/HEIGHT, 0.1, 2000.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 gluLookAt(0.0, 1000.0, 1000.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

 //階層アニメーション
 hierarchy->Animation_Draw(0,CurrentFrame);

  glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
  glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);

 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 wstr=L"最大フレーム[";
 _itow_s(hierarchy->Animation_MaxFrame,wchar,255,10);
 wstr+=wchar;
 wstr+=L"]";
 font->DrawStringW(0,16,(wchar_t *)wstr.c_str());
 wstr=L"現在のフレーム[";
 _itow_s(CurrentFrame,wchar,255,10);
 wstr+=wchar;
 wstr+=L"]";
 font->DrawStringW(0,32,(wchar_t *)wstr.c_str());

 glutSwapBuffers();
}
void idle(void)
{
 if(hierarchy->Animation_MaxFrame<CurrentFrame)CurrentFrame=0;
 Sleep(1);
 glutPostRedisplay();
}
//タイマー
void timer(int value) {
 CurrentFrame+=150;
 glutTimerFunc(100 , timer , 0);
}

void Init(){
 glClearColor(0.0, 0.0, 0.0, 1.0);
 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHTING);
 glEnable(GL_CULL_FACE);
 glCullFace(GL_BACK);

 hierarchy = new HIERARCHY("sample2.x",100);
 font = new GLFONT(L"MS明朝", 16);

}
int main(int argc, char *argv[])
{
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 glutCreateWindow("キーフレーム");
 glutDisplayFunc(display);
 glutIdleFunc(idle);
 glutTimerFunc(100 , timer , 0);
 Init();
 glutMainLoop();
 return 0;
}

 

 

 

最終更新:2014年04月16日 19:14
添付ファイル