#pragma once
#include "PNG.h"
#include <math.h>
#define PAI 3.14159
using namespace std;
struct MATRIX;
//クォータニオン構造体
struct QUATERNION{
union {
struct {
float w;
float x;
float y;
float z;
};
float Index[4];
};
MATRIX ToMatrix();//クォータニオンを回転行列にする
}qua;
//マトリクス構造体
struct MATRIX {
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
float mat_4x4[4][4];
float mat_16[16];
};
MATRIX(){//単位行列に初期化
for(int i=0;i<16;i++){
this->mat_16[i]=0;
}
this->_11=this->_22=this->_33=this->_44=1;
}
void PRINT(char* text){
printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",
text,
this->_11,this->_21,this->_31,this->_41,
this->_12,this->_22,this->_32,this->_42,
this->_13,this->_23,this->_33,this->_43,
this->_14,this->_24,this->_34,this->_44);
}
MATRIX Multiplication(MATRIX& mat);//合成
QUATERNION ToQuaternion();//回転行列をクォータニオンにする
};
//合成
MATRIX MATRIX::Multiplication(MATRIX& mat)
{
MATRIX ret;
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
ret.mat_16[y*4+x]=mat.mat_16[y*4]*this->mat_16[x]+mat.mat_16[y*4+1]*this->mat_16[x+4]+mat.mat_16[y*4+2]*this->mat_16[x+8]+mat.mat_16[y*4+3]*this->mat_16[x+12];
}
}
return ret;
}
float SGN(float x) {
return (x >= 0.0f) ? +1.0f : -1.0f;
}
//回転行列をクォータニオンにする
QUATERNION MATRIX::ToQuaternion(){
QUATERNION q;
q.w = ( this->_11 + this->_22 + this->_33 + 1.0f) / 4.0f;
q.x = ( this->_11 - this->_22 - this->_33 + 1.0f) / 4.0f;
q.y = (-this->_11 + this->_22 - this->_33 + 1.0f) / 4.0f;
q.z = (-this->_11 - this->_22 + this->_33 + 1.0f) / 4.0f;
for(int i=0;i<4;i++){
if(q.Index[i] < 0.0f) q.Index[i] = 0.0f;
q.Index[i] = sqrt(q.Index[i]);
}
if(q.w >= q.x && q.w >= q.y && q.w >= q.z) {
q.w *= +1.0f;
q.x *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21);
q.y *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21);
q.z *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21);
} else {
q.w *= +1.0f*-1;
q.x *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21)*-1;
q.y *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21)*-1;
q.z *= SGN(this->_23 - this->_32)*SGN(this->_31 -
this->_13)*SGN(this->_12 - this->_21)*-1;
}
float nor = sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z *q.z);
for(int i=0;i<4;i++){
q.Index[i] /= nor;
}
return q;
}
//クォータニオンを回転行列にする
MATRIX QUATERNION::ToMatrix(){
MATRIX ret;
float sx = this->x * this->x;
float sy = this->y * this->y;
float sz = this->z * this->z;
float cx = this->y * this->z;
float cy = this->x * this->z;
float cz = this->x * this->y;
float wx = this->w * this->x;
float wy = this->w * this->y;
float wz = this->w * this->z;
ret._11= 1.0f - 2.0f * (sy + sz);
ret._12= 2.0f * (cz + wz);
ret._13= 2.0f * (cy - wy);
ret._21= 2.0f * (cz - wz);
ret._22= 1.0f - 2.0f * (sx + sz);
ret._23= 2.0f * (cx + wx);
ret._31= 2.0f * (cy + wy);
ret._32= 2.0f * (cx - wx);
ret._33= 1.0f - 2.0f * (sx + sy);
ret._41= 0.0f;
ret._42= 0.0f;
ret._43= 0.0f;
return ret;
}
//3つのベクトル
struct Vector3f{
float x;
float y;
float z;
Vector3f(){};
Vector3f(float _x,float _y,float _z){
x=_x;y=_y;z=_z;
};
}vec3d;
Vector3f & operator*(Vector3f &v,float size){
v.x *= size;
v.y *= size;
v.z *= size;
return v;
}
Vector3f & operator+(Vector3f &a,Vector3f &b){
a.x+=b.x;
a.y+=b.y;
a.z+=b.z;
return a;
}
//4つのベクトル
struct Vector4f{
union {
struct {
float x;
float y;
float z;
float w;
};
float Index[4];
};
Vector4f(){};
Vector4f(float _x,float _y,float _z,float _w){
x=_x;y=_y;z=_z;w=_w;
};
Vector4f GeometricTransform(MATRIX& mat);//幾何変換
}vec4d;
Vector4f Vector4f::GeometricTransform(MATRIX &mat){
Vector4f ret;
for(int y=0;y<4;y++){
ret.Index[y]=mat.mat_16[y]*this->x+mat.mat_16[y+4]*this->y+mat.mat_16[y+8]*this->z+mat.mat_16[y+12]*this->w;
}
return ret;
}
//正規化
void normalize(Vector3f& v){
float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
if(m > 0.0f){m = 1.0f / m;}else{m = 0.0f;}
v.x*=m;
v.y*=m;
v.z*=m;
}
//外積
void cross( Vector3f& src1, Vector3f& src2 ,Vector3f& dst){
dst.x = src1.y*src2.z - src1.z*src2.y;
dst.y = src1.z*src2.x - src1.x*src2.z;
dst.z = src1.x*src2.y - src1.y*src2.x;
}
//内積
void dot(Vector3f& src1,Vector3f& src2,float& dst){
dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;
}
//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;
Vector3f TriView;
}Tri;
//ポリゴンデータ
struct Quadrangle{
Vector3f QuadVer;
Vector3f QuadNor;
UV QuadUV;
}Quad;
//フレーム外マテリアル構造体
struct OUTSIDEMATERIAL{
string MaterialName;//マテリアル名
Reflection4 MaterialColor;//反射
float Shininess;//shininess
string TextureName;//テクスチャ名
int TexNo;//テクスチャNO.
}outmtl;
//マテリアル構造体
struct MATERIAL{
string MaterialName;//マテリアル名
Reflection4 MaterialColor;//反射
float Shininess;//shininess
string TextureName;//テクスチャ名
int TexNo;//テクスチャNO.
vector <Triangle> Tridata;//三角面データ
vector <Quadrangle> Quaddata;//四角面データ
}mtl;
//メッシュ構造体
struct MESH{
public:
vector <MATERIAL> Material;//マテリアル
vector <TEXTURE*> TexData;//テクスチャデータ
vector<GLuint> TexID;//テクスチャID
GLuint TexID2;//代入用
TEXTURE* tex;//代入用
}msh;
//ボーン構造体
struct BONE{
public:
string Bone_Name;//ボーン名
vector<int>SkinID;//スキンインデックス
vector<float>SkinWeights;//スキンウェイト
MATRIX bone_ofset;//ボーンオフセット行列
MATRIX CurrentFrame;//現在の行列
}bne;
//アニメーションデータ構造体
struct ANIMATION{
public:
vector <int> Key;//アニメーションキー
vector <MATRIX> Matrix;//行列データ
}anm;
//ノード構造体
struct NODE{
NODE* Node;//子ノード
NODE* Next;//隣の階層
string FrameName;//フレーム名
MESH* Mesh;//メッシュ
BONE* Bone;//ボーン
vector<GLuint> MatNo;//マテリアルNO.
ANIMATION Anim;//アニメーションデータ
MATRIX FrameTransformMatrix;//親フレームからのトランスフォーム行列
}nde;
//階層メッシュクラス
class HIERARCHY{
public:
void Draw();//描画
void Draw_Frame(NODE& node,int Frame_Time,MATRIX& mat);//フレーム描画
void Animation_Draw(int Animation_NO,int Frame);//アニメーション描画
HIERARCHY();
HIERARCHY(char* FileName,float size);
NODE Root;//ルートノード
float Size;//サイズ
int Animation_MaxFrame;//最大フレーム
private:
bool Load_Mesh(FILE& fp,NODE& node);//メッシュ読み込み
QUATERNION Spherical_Linear_Interpolation( QUATERNION& q1, QUATERNION&
q2, float t);//球面線形補間
char buffer[255];
protected:
NODE* pNode;//ノードポインタ
int Back;//階層戻し
void Init();
bool Load_Hierarchy(char* FileName); //階層メッシュ読み込み
bool Load_Frame(FILE& fp,NODE& node,int& hierarchy);
//フレーム読み込み
bool Load_Animation(FILE& fp);//アニメーション読み込み
void Find_Frame(NODE& node,char* name);//フレームを探す
MATRIX Linear_Interpolation(MATRIX& a,MATRIX& b,float t);//線形補間
vector<OUTSIDEMATERIAL> OutSide_Mat;//フレーム外マテリアル
vector<BONE> Bone;//ボーン情報
vector<Vector3f> Vertex;//頂点グループ
vector<Vector3f> VertexView;//頂点グループ
vector<Vector3f> Normal;//法線グループ
vector<int> VertexIndex;//頂点インデックス
vector<int> FaceIndex;//面インデックス
vector<int> NormalIndex;//法線インデックス
vector<int> MaterialIndex;//マテリアルインデックス
vector<UV> uv;//UV
void DataCreate(NODE& node);
void ViewDataCreate(NODE& node);
};
//スキンメッシュクラス
class SKINNEDMESH : public HIERARCHY{
public:
bool SkinnedMeshFlag;//スキンメッシュか階層メッシュか
int AnimTicksPerSecond;//一秒間のコマ数
bool Load_SkinnedMesh(char* FileName, float size);//スキンメッシュ読み込み
SKINNEDMESH();
SKINNEDMESH(char* FileName,float size);
float Draw_Joint(NODE& node,int Frame_Time,MATRIX& mat);//ジョイント描画
void Draw_Bone(MATRIX mat,float length);//ボーン描画
void Calc_Bone(NODE& node,int Frame_Time,MATRIX& mat);//ボーン計算
};
SKINNEDMESH::SKINNEDMESH(){
SkinnedMeshFlag=false;
AnimTicksPerSecond=60;
Size=1;
Animation_MaxFrame=0;
}
SKINNEDMESH::SKINNEDMESH(char *FileName, float size){
//階層メッシュアニメーションかスキンメッシュアニメーションかの判定
char key[255];
FILE* fp=NULL;
SkinnedMeshFlag=false;
AnimTicksPerSecond=60;
Animation_MaxFrame=0;
fopen_s(&fp,FileName,"rt");
//読み込み
fseek(fp,0,SEEK_SET);
while(!feof(fp)){
//キーワード 読み込み
ZeroMemory(key,sizeof(key));
fscanf_s(fp,"%s ",key,sizeof(key));
//テンプレート読み飛ばし
if(strcmp(key,"template")==0){
while(strcmp(key,"}")){
fscanf_s(fp,"%s ",key,sizeof(key));
}
continue;
}
if(strcmp(key,"AnimTicksPerSecond")==0){
fgets(key,sizeof(key),fp);
fscanf_s(fp,"%d;",&AnimTicksPerSecond);
}
if((strcmp(key,"FrameTransformMatrix")==0)||(strcmp(key,"XSkinMeshHeader")==0)||
(strcmp(key,"VertexDuplicationIndices")==0)||(strcmp(key,"SkinWeights")==0)){
SkinnedMeshFlag=true;
}
}
if(SkinnedMeshFlag){//スキンメッシュアニメーションなら
Init();
Size=size;
Load_SkinnedMesh(FileName,size);
}else{//階層メッシュアニメーションなら
Init();
Size=size;
this->Load_Hierarchy(FileName);
}
}
//データ作成
void HIERARCHY::ViewDataCreate(NODE& node){
int Count=0;
//マテリアル毎のデータを作成
for(int i=0;i<(signed)MaterialIndex.size();i++){
if(FaceIndex[i]==3){
for(int j=0;j<3;j++){
Tri.TriVer=VertexView[VertexIndex[Count+j]];
Tri.TriNor=Normal[NormalIndex[Count+j]];
//Tri.TriUV=uv[VertexIndex[Count+j]];
Tri.TriView=VertexView[VertexIndex[Count+j]];
node.Mesh->Material[MaterialIndex[i]].Tridata[Count+j]=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;
}
}
}
//ボーン計算
void SKINNEDMESH::Calc_Bone(NODE& node,int Frame_Time,MATRIX& mat){
MATRIX current=mat;
while(1){
if(node.Bone!=NULL){
if(node.Anim.Key.size()==0){
mat=mat.Multiplication(node.FrameTransformMatrix);
}else{
//線形補間
for(int k=1;k<(signed)node.Anim.Key.size();k++){
int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ
int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置
float t=(float)Current/(float)Length;
if((node.Anim.Key[k-1]<=Frame_Time)&&(node.Anim.Key[k]>Frame_Time)){
MATRIX Linear =
Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);
mat=mat.Multiplication(Linear);
}
}
}
for(int i=0;i<(signed)Bone.size();i++){
if(node.Bone->Bone_Name==Bone[i].Bone_Name)Bone[i].CurrentFrame=mat;
}
}
//スキンメッシュアニメーションの具体的な処理↓(わかりやすくするため、あえてこのような記述にしてあります。)
if(node.Mesh!=NULL){
for(int i=0;i<(signed)Vertex.size();i++){
vec4d.x=Vertex[i].x;vec4d.y=Vertex[i].y;vec4d.z=Vertex[i].z;vec4d.w=1.0;
Vector4f ret8=vec4d.GeometricTransform(Bone[3].bone_ofset);
Vector4f ret7=ret8.GeometricTransform(Bone[3].CurrentFrame);
Vector4f ret6=vec4d.GeometricTransform(Bone[2].bone_ofset);
Vector4f ret5=ret6.GeometricTransform(Bone[2].CurrentFrame);
Vector4f ret4=vec4d.GeometricTransform(Bone[1].bone_ofset);
Vector4f ret3=ret4.GeometricTransform(Bone[1].CurrentFrame);
Vector4f ret2=vec4d.GeometricTransform(Bone[0].bone_ofset);
Vector4f ret=ret2.GeometricTransform(Bone[0].CurrentFrame);
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];
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];
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];
VertexView[i]=vec3d;
}
ViewDataCreate(node);
}
if(node.Node!=NULL)Calc_Bone(*node.Node,Frame_Time,mat);
if(node.Next!=NULL)Calc_Bone(*node.Next,Frame_Time,current);
return;
}
return;
}
//ボーン描画
void SKINNEDMESH::Draw_Bone(MATRIX mat,float length){
glColor4f(0.0f,1.0f,1.0f,1.0f);
glPushMatrix();
glMultMatrixf(&mat.mat_16[0]);
glRotatef(90.0f,1.0f,0.0f,0.0f);
if(mat._41+mat._42+mat._43!=0){
if(length!=0)glutSolidCone(10.0f*Size, length, 4, 1);
}
glPopMatrix();
}
//ジョイント描画
float SKINNEDMESH::Draw_Joint(NODE& node,int Frame_Time,MATRIX&
mat){
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
MATRIX current=mat;
MATRIX ret;
float length=0;
while(1){
if(node.Bone!=NULL){
glPushMatrix();
if(node.Anim.Key.size()==0){
mat=mat.Multiplication(node.FrameTransformMatrix);
}else{
//線形補間
for(int k=1;k<(signed)node.Anim.Key.size();k++){
int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ
int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置
float t=(float)Current/(float)Length;
if((node.Anim.Key[k-1]<=Frame_Time)&&(node.Anim.Key[k]>Frame_Time)){
MATRIX Linear =
Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);
mat=mat.Multiplication(Linear);
}
}
}
glMultMatrixf(&mat.mat_16[0]);
glColor4f(1.0f,1.0f,0.0f,1.0f);
glutSolidSphere(5.0*Size,8,8);
ret=mat;
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));
glPopMatrix();
}
float len=0;
if(node.Node!=NULL)len=Draw_Joint(*node.Node,Frame_Time,mat);
if(node.Next!=NULL)len=Draw_Joint(*node.Next,Frame_Time,current);
Draw_Bone(ret,len);
return length;
}
glDisable(GL_COLOR_MATERIAL);
return 0;
}
bool SKINNEDMESH::Load_SkinnedMesh(char *FileName, float size){
//Xファイルを開いて内容を読み込む
Back=-1;
int Hierarchy=0;
FILE* fp=NULL;
fopen_s(&fp,FileName,"rt");
//読み込み
fseek(fp,0,SEEK_SET);
Load_Frame(*fp,Root,Hierarchy);
//ボーン情報をセット
for(int i=0;i<(signed)Bone.size();i++){
Find_Frame(Root,(char*)Bone[i].Bone_Name.c_str());
pNode->Bone=&Bone[i];
}
fseek(fp,0,SEEK_SET);
this->Load_Animation(*fp);
fclose(fp);
return true;
}
//コンストラクタ
HIERARCHY::HIERARCHY(){
Init();
}
//コンストラクタ
HIERARCHY::HIERARCHY(char* FileName,float size){
Init();
Size=size;
Animation_MaxFrame=0;
Load_Hierarchy(FileName);
}
//初期化
void HIERARCHY::Init(){
Root.Node=NULL;
Root.Next=NULL;
Root.FrameName="Root";
Root.Mesh=NULL;
Root.Bone=NULL;
}
//球面線形補間
QUATERNION HIERARCHY::Spherical_Linear_Interpolation( QUATERNION& q1,
QUATERNION& q2, float t)
{
QUATERNION q;
if((q1.w==q2.w)&&(q1.x==q2.x)&&(q1.y==q2.y)&&(q1.z==q2.z)){
for(int i=0;i<4;i++){
q.Index[i] = q1.Index[i];
}
return q;
}
float qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;
float ss = 1.0f - qr * qr;
if (ss == 0.0f) {
for(int i=0;i<4;i++){
q.Index[i] = q1.Index[i];
}
return q;
}else{
float sp = sqrt(ss);
float ph = acos(qr);
float pt = ph * t;
float t1 = sin(pt) / sp;
float t0 = sin(ph - pt) / sp;
for(int i=0;i<4;i++){
q.Index[i] = (q1.Index[i] * t0 + q2.Index[i] * t1);
}
return q;
}
}
//線形補間
MATRIX HIERARCHY::Linear_Interpolation(MATRIX& a,MATRIX& b,float
t){
MATRIX ret,r1,r2,r3;
QUATERNION q1,q2,q3;
Vector3f vec_A, vec_B, vec_R;
//平行移動
vec_A.x=a._41;
vec_A.y=a._42;
vec_A.z=a._43;
vec_B.x=b._41;
vec_B.y=b._42;
vec_B.z=b._43;
vec_R=vec_A*(1.0f-t) + vec_B*t;
ret._41=vec_R.x;
ret._42=vec_R.y;
ret._43=vec_R.z;
//スケーリング成分抜き出し
vec_A.x=sqrt(a._11*a._11+a._21*a._21+a._31*a._31);
vec_A.y=sqrt(a._12*a._12+a._22*a._22+a._32*a._32);
vec_A.z=sqrt(a._13*a._13+a._23*a._23+a._33*a._33);
vec_B.x=sqrt(b._11*b._11+b._21*b._21+b._31*b._31);
vec_B.y=sqrt(b._12*b._12+b._22*b._22+b._32*b._32);
vec_B.z=sqrt(b._13*b._13+b._23*b._23+b._33*b._33);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
r1.mat_4x4[j][i]=a.mat_4x4[j][i];
r2.mat_4x4[j][i]=b.mat_4x4[j][i];
if(i==0){if(j<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;}}
if(i==1){if(j<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;}}
if(i==2){if(j<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;}}
}
}
//クォータニオンを補間
q1=r1.ToQuaternion();
q2=r2.ToQuaternion();
q3=Spherical_Linear_Interpolation(q1,q2,t);
r3=q3.ToMatrix();
vec_R=vec_A*(1.0f-t) + vec_B*t;
ret._11=r3._11*vec_R.x;
ret._21=r3._21*vec_R.x;
ret._31=r3._31*vec_R.x;
ret._12=r3._12*vec_R.y;
ret._22=r3._22*vec_R.y;
ret._32=r3._32*vec_R.y;
ret._13=r3._13*vec_R.z;
ret._23=r3._23*vec_R.z;
ret._33=r3._33*vec_R.z;
return ret;
}
//フレーム描画
void HIERARCHY::Draw_Frame(NODE& node,int Frame_Time,MATRIX& mat){
MATRIX current=mat;
while(1){
if(node.Mesh!=NULL){
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glPushMatrix();
glMultMatrixf(&mat.mat_16[0]);
//線形補間
for(int k=1;k<(signed)node.Anim.Key.size();k++){
int Length=node.Anim.Key[k]-node.Anim.Key[k-1];//キー間の長さ
int Current=Frame_Time-node.Anim.Key[k-1];//キー間の現在位置
float t=(float)Current/(float)Length;
if((node.Anim.Key[k-1]<=Frame_Time)&&(node.Anim.Key[k]>Frame_Time)){
MATRIX Linear =
Linear_Interpolation(node.Anim.Matrix[k-1],node.Anim.Matrix[k],t);
mat=mat.Multiplication(Linear);
glMultMatrixf(&Linear.mat_16[0]);
}
}
for(int i=0;i<(signed)node.Mesh->Material.size();i++){
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);
}
if(node.Mesh->Material[i].Tridata.size()>1){
//glVertexPointer(3, GL_FLOAT,sizeof(Tri) ,
&node.Mesh->Material[i].Tridata[0].TriVer.x);
glVertexPointer(3, GL_FLOAT,sizeof(Tri) ,
&node.Mesh->Material[i].Tridata[0].TriView.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());
}
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
if(node.Node!=NULL)Draw_Frame(*node.Node,Frame_Time,mat);
if(node.Next!=NULL)Draw_Frame(*node.Next,Frame_Time,current);
if(node.Node==NULL)return;
if(node.Next==NULL)return;
return;
}
}
//アニメーション描画
void HIERARCHY::Animation_Draw(int Animation_NO,int Frame){
MATRIX mat;
Draw_Frame(Root,Frame,mat);
}
//描画
void HIERARCHY::Draw(){
MATRIX mat;
Draw_Frame(Root,0,mat);
}
//フレームを探す
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];
char *next;
int hierarchy=0,count=0,key=0,dummy=0,x=0,y=0,z=0,w=0;
//合成行列
MATRIX mix;
//読み込み
while(!feof(&fp))
{
ZeroMemory(buf,sizeof(buf));
fscanf_s(&fp,"%s ",buf,sizeof(buf));
//テンプレート読み飛ばし
if(strcmp(buf,"template")==0){
while(strcmp(buf,"}")){
fscanf_s(&fp,"%s ",buf,sizeof(buf));
}
continue;
}
//AnimationSetを探す
if(strcmp(buf,"AnimationSet")==0){
while(!feof(&fp))
{
fgets(buf,sizeof(buf),&fp);
if((!strstr(buf,"Animation")==NULL)&&(strstr(buf,"Animation_")==NULL)){
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);
if((!strstr(buf,"{")==NULL)&&(!strstr(buf,"}")==NULL)){//名前の抽出
sscanf_s(buf," { %s } ",&name,sizeof(name));
strtok_s( name, "}" ,&next);
pNode=NULL;
Find_Frame(Root,name);
while(!feof(&fp)){
fgets(buf,sizeof(buf),&fp);
if(!strstr(buf,"AnimationKey")==NULL){
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);//キータイプ 4…行列タイプ]
if(strstr(buf,"4;")==NULL)printf("対応していません");
fgets(buf,sizeof(buf),&fp);//キー数
count=atoi(buf);
for(int i=0;i<count;i++){
fscanf_s(&fp,"%d;%d;",&key,&dummy);//キーの位置;データの数
if((count-1==i)&&(Animation_MaxFrame<key))Animation_MaxFrame=key;
pNode->Anim.Key.push_back(key);
if(dummy!=16)printf("対応していません");
fscanf_s(&fp,"%f,%f,%f,%f,",&mix.mat_16[0],&mix.mat_16[1],&mix.mat_16[2],&mix.mat_16[3]);
fscanf_s(&fp,"%f,%f,%f,%f,",&mix.mat_16[4],&mix.mat_16[5],&mix.mat_16[6],&mix.mat_16[7]);
fscanf_s(&fp,"%f,%f,%f,%f,",&mix.mat_16[8],&mix.mat_16[9],&mix.mat_16[10],&mix.mat_16[11]);
fscanf_s(&fp,"%f,%f,%f,%f;;",&mix.mat_16[12],&mix.mat_16[13],&mix.mat_16[14],&mix.mat_16[15]);
fgets(buf,sizeof(buf),&fp);
mix._41*=Size;
mix._42*=Size;
mix._43*=Size;
pNode->Anim.Matrix.push_back(mix);
}
break;
}
}
}
}
}
}
}
return true;
}
//データ作成
void HIERARCHY::DataCreate(NODE& node){
int 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]];
Tri.TriView=Vertex[VertexIndex[Count+j]];
if(MaterialIndex[i]>=(signed)node.Mesh->Material.size()){
mtl.MaterialName=this->OutSide_Mat[MaterialIndex[i]].MaterialName;
mtl.MaterialColor=this->OutSide_Mat[MaterialIndex[i]].MaterialColor;
mtl.Shininess=this->OutSide_Mat[MaterialIndex[i]].Shininess;
node.Mesh->Material.push_back(mtl);
}
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;
}
}
}
//メッシュ読み込み
bool HIERARCHY::Load_Mesh(FILE& fp,NODE& node){
char key[255];
char buf[255];
int v1=0,v2=0,v3=0,v4=0;
int Count=0,matCount=0,Hierarchy=1;
string str="";
fscanf_s(&fp,"%s ",key,sizeof(key));
node.Mesh=NULL;
//読み込み
while(!feof(&fp))
{
//キーワード 読み込み
ZeroMemory(key,sizeof(key));
fscanf_s(&fp,"%s ",key,sizeof(key));
//階層+
if(strcmp(key,"{")==0){
Hierarchy++;
}
//階層-
if(strcmp(key,"}")==0){
Hierarchy--;
if(Hierarchy==0){
if(node.Mesh!=NULL)DataCreate(node);
return true;
}
}
if(strcmp(key,"Frame")==0){
if(node.Mesh!=NULL)DataCreate(node);
return true;
}
//頂点 読み込み
if(strcmp(key,"Mesh")==0)
{
node.Mesh =new MESH(msh);
Hierarchy++;
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);
Count=atoi(buf);
for(int i=0;i<Count ;i++)
{
fscanf_s(&fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
Vertex.push_back(vec3d*(float)Size);
VertexView.push_back(vec3d*(float)Size);
}
//頂点インデックス読み込み
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);
while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&fp);}//空行対策
Count=atoi(buf);
for(int i=0;i<Count ;i++)
{
int dammy=0;
fgets(buf,sizeof(buf),&fp);
str=buf;
string::size_type first = str.find_first_not_of(' ');
string::size_type tab = str.find_first_not_of('\t');
string::size_type index = str.find("3;");
if(index-first-tab==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-first-tab==0)){
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)
{
Hierarchy++;
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);
Count=atoi(buf);
for(int i=0;i<Count ;i++)
{
fscanf_s(&fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
Normal.push_back(vec3d);
}
//法線インデックス読み込み
fgets(buf,sizeof(buf),&fp);
fgets(buf,sizeof(buf),&fp);
while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),&fp);}//空行対策
Count=atoi(buf);
for(int i=0;i<Count ;i++)
{
int dammy=0;
fgets(buf,sizeof(buf),&fp);
str=buf;
string::size_type first = str.find_first_not_of(' ');
string::size_type tab = str.find_first_not_of('\t');
string::size_type index = str.find("3;");
if(index-first-tab==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-first-tab==0)){
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)
{
Hierarchy++;
fgets(buf,sizeof(buf),&fp);//空改行
fgets(buf,sizeof(buf),&fp);//マテリアル数
matCount=atoi(buf);
fgets(buf,sizeof(buf),&fp);//リスト要素数
Count=atoi(buf);
for(int i=0;i<Count;i++)
{
fgets(buf,sizeof(buf),&fp);
int test=atoi(buf);
MaterialIndex.push_back(test);
}
char *next;
for(int i=0;i<matCount;i++)
{
fgets(buf,sizeof(buf),&fp);
sscanf_s(buf," { %s } ",&buf,sizeof(buf));
strtok_s( buf, "}" ,&next);
for(int j=0;j<(signed)this->OutSide_Mat.size();j++){
if(strcmp(this->OutSide_Mat[j].MaterialName.c_str(),buf)==0)node.MatNo.push_back(j);
}
}
}
}
return false;
}
//フレーム読み込み
bool HIERARCHY::Load_Frame(FILE& fp,NODE& node,int& hierarchy){
char key[255];
char *next;
int begin=0,end=0;
int current=hierarchy;//現在の階層
int file_pos;
int count;
int ID=0;
float skinweights=0.0f;
MATRIX dum;
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,"Material")==0)
{
begin++;
fgets(key,sizeof(key),&fp);
strtok_s( key, "\n" ,&next);
outmtl.MaterialName=key;
fgets(key,sizeof(key),&fp);
//ディフューズ
fscanf_s(&fp,"%f;%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z,&vec4d.w);
outmtl.MaterialColor.diffuse=(const Color4 &)vec4d;
//SHININESS
fscanf_s(&fp,"%f;",&outmtl.Shininess);
//スペキュラー
fscanf_s(&fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
outmtl.MaterialColor.specular=(const Color4 &)vec4d;
//エミッシブ
fscanf_s(&fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
outmtl.MaterialColor.ambient=(const Color4 &)vec4d;
this->OutSide_Mat.push_back(outmtl);
}
//ボーン
if(strcmp(key,"SkinWeights")==0){
begin++;
fgets(key,sizeof(key),&fp);
fscanf_s(&fp,"%s;",key,sizeof(key));
sscanf_s(key,"\"%s\";",&key,sizeof(key));
strtok_s( key, "\"" ,&next);
bne.Bone_Name=key;
fgets(key,sizeof(key),&fp);
fgets(key,sizeof(key),&fp);
count=atoi(key);
for(int i=0;i<count;i++){
fscanf_s(&fp,"%d,",&ID);
bne.SkinID.push_back(ID);
}
fscanf_s(&fp,"%s;",key,sizeof(key));
for(int i=0;i<count;i++){
fscanf_s(&fp,"%f,",&skinweights);
bne.SkinWeights.push_back(skinweights);
}
fscanf_s(&fp,"%s;",key,sizeof(key));
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[0],&dum.mat_16[1],&dum.mat_16[2],&dum.mat_16[3]);
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[4],&dum.mat_16[5],&dum.mat_16[6],&dum.mat_16[7]);
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[8],&dum.mat_16[9],&dum.mat_16[10],&dum.mat_16[11]);
fscanf_s(&fp,"%f,%f,%f,%f;;",&dum.mat_16[12],&dum.mat_16[13],&dum.mat_16[14],&dum.mat_16[15]);
bne.bone_ofset=dum;
Bone.push_back(bne);
bne.SkinID.clear();
bne.SkinWeights.clear();
}
//親フレームからのトランスフォーム行列
if(strcmp(key,"FrameTransformMatrix")==0){
begin++;
fgets(key,sizeof(key),&fp);
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[0],&dum.mat_16[1],&dum.mat_16[2],&dum.mat_16[3]);
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[4],&dum.mat_16[5],&dum.mat_16[6],&dum.mat_16[7]);
fscanf_s(&fp,"%f,%f,%f,%f,",&dum.mat_16[8],&dum.mat_16[9],&dum.mat_16[10],&dum.mat_16[11]);
fscanf_s(&fp,"%f,%f,%f,%f;;",&dum.mat_16[12],&dum.mat_16[13],&dum.mat_16[14],&dum.mat_16[15]);
node.FrameTransformMatrix=dum;
node.FrameTransformMatrix._41*=Size;
node.FrameTransformMatrix._42*=Size;
node.FrameTransformMatrix._43*=Size;
}
//フレーム
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<current))return true;
}
}
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;
}
|