#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 <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 NODE{
NODE* Node;//子ノード
NODE* Next;//隣の階層
string FrameName;//フレーム名
MESH* Mesh;//メッシュ
}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);//メッシュ読み込み
void Draw();//描画
void Draw_Frame(NODE& node);
void Init();
HIERARCHY();
HIERARCHY(char* FileName,int size);
NODE Root;//ルートノード
int Size;//サイズ
int Back;//階層戻し
char buffer[255];
};
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){
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);
}
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);
if(node.Next!=NULL)Draw_Frame(*node.Next);
if(node.Node==NULL)return;
if(node.Next==NULL)return;
return;
}
}
void HIERARCHY::Draw(){
Draw_Frame(Root);
}
//メッシュ読み込み
bool HIERARCHY::Load_Mesh(FILE& fp,NODE& node){
vector <Vector3f> Vertex;//頂点
vector <Vector3f> Normal;//法線
vector <UV> uv;//UV
vector <int> VertexIndex;
vector <int> NormalIndex;
vector <int> MaterialIndex;
vector <int> 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<Count ;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<Count ;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<Count ;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<Count ;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<Count;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<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);
fclose(fp);
return true;
}
|