#include <string>
#include <vector>
#include "PNG.h"
using namespace std;
//3つのベクトル
struct Vector3f{
float x;
float y;
float z;
};
//4つのベクトル
struct Vector4f{
float x;
float y;
float z;
float w;
};
//4つの反射
struct Reflection4{
float diffuse;
float ambient;
float emission;
float specular;
};
//4つのカラー
struct Color4{
float r;
float g;
float b;
float a;
};
//UV座標
struct UV{
float u;//u値
float v;//v値
};
//面情報構造体
struct POLYGON{
bool Polygon;//3角か4角か true=4;false=3;
GLuint Index[4];//インデックス
int MaterialID;//マテリアルNo.
UV uv[4];//UV情報
};
//ポリゴンデータ
struct GROUP{
bool Texture_Use;//テクスチャを使うか
vector<Vector3f> TriVer;//3角頂点データ
vector<Vector3f> QuadVer;//4角頂点データ
vector<float> TriUV;//3角UV
vector<float> QuadUV;//4角UV
}gro;
//オブジェクト構造体
struct OBJECT{
bool View;//表示するか
string Name;//オブジェクト名
vector<GROUP> Group;//マテリアル毎のグループ
}obj;
//マテリアル構造体
struct MATERIAL{
int MaterialID;//ID
string MaterialName;//マテリアル名
Color4 Color;//カラー
Reflection4 ReflectionColor;//反射
float Power;//shiness
string TextureName;//テクスチャ名
}mtl;
//モデルクラス
class MODEL{
protected:
FILE* fp;//ファイルポインタ
char buf[255];//読み込み用バッファ
string str;
TEXTURE* tex2;
GLuint texture2;
//読み込み用
vector<Vector3f> Vertex;//頂点データ
POLYGON Poly;//面情報
void Vertex_Set();//頂点情報セット
void Material_Set();//マテリアル情報セット
void Face_Set();//面情報セット
string Split(string* str,char str1,char str2);//文字列分離
public:
MODEL();
MODEL(char* FileName);//コンストラクタ
vector<MATERIAL> Material;//マテリアル
vector<OBJECT> Object;//オブジェクトデータ
vector<TEXTURE*> tex;//テクスチャデータ
vector<GLuint> texture;//テクスチャID
bool MQO_Load(char* FileName);//ロード
void DRAW();//描画
};
MODEL::MODEL(){
}
MODEL::MODEL(char* FileName){
MQO_Load(FileName);
}
//文字列分離
string MODEL::Split(string *str, char str1, char str2){
string::size_type start = str->find(str1);
string::size_type end = str->rfind(str2);
return str->substr(start+1,end-start-1);
}
//モデル描画
void MODEL::DRAW(){
glEnableClientState(GL_VERTEX_ARRAY);
for(int i=0;i<(signed)Object.size();i++){
if(Object[i].View){
for(int j=0;j<(signed)Object[i].Group.size();j++){
GLfloat material[] = { Material[j].Color.r, Material[j].Color.g,
Material[j].Color.b, Material[j].Color.a };
glMaterialfv(GL_FRONT, GL_DIFFUSE, material);
if(Object[i].Group[j].Texture_Use){
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, texture[j]);
}else{
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if(0<Object[i].Group[j].TriUV.size())glTexCoordPointer(2,GL_FLOAT,0,&Object[i].Group[j].TriUV[0]);
if(0<Object[i].Group[j].TriVer.size()){
glVertexPointer(3,GL_FLOAT,0,&Object[i].Group[j].TriVer[0]);
glDrawArrays(GL_TRIANGLES,0,Object[i].Group[j].TriVer.size());
}
if(0<Object[i].Group[j].QuadUV.size())glTexCoordPointer(2,GL_FLOAT,0,&Object[i].Group[j].QuadUV[0]);
if(0<(signed)Object[i].Group[j].QuadVer.size()){
glVertexPointer(3,GL_FLOAT,0,&Object[i].Group[j].QuadVer[0]);
glDrawArrays(GL_QUADS,0,Object[i].Group[j].QuadVer.size());
}
}}
}
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
//マテリアルセット
void MODEL::Material_Set(){
int mat;
fscanf_s(fp, "%d", &mat);//マテリアル数
fscanf_s(fp, "%s", buf,255);//"{"を読み飛ばす
for(int i=0;i<mat;i++){
Material.push_back(mtl);
fscanf_s(fp, "%s", buf,255);//マテリアル名格納
str=buf;
Material[Material.size()-1].MaterialName=Split(&str,'\"','\"');//""を除去
fgets(buf,255,fp);
char* buf2;
if((buf2 = strstr(buf,"col(")) != NULL ){//マテリアルカラー格納
sscanf_s(buf2,"col(%f %f %f %f)", &Material[Material.size()-1].Color.r,
&Material[Material.size()-1].Color.g,
&Material[Material.size()-1].Color.b,
&Material[Material.size()-1].Color.a);
}
if((buf2 = strstr(buf,"dif(")) != NULL ){//ディフューズ格納
sscanf_s(buf2,"dif(%f)",
&Material[Material.size()-1].ReflectionColor.diffuse);
}
if((buf2 = strstr(buf,"amb(")) != NULL ){//アンビエント格納
sscanf_s(buf2,"amb(%f)",
&Material[Material.size()-1].ReflectionColor.ambient);
}
if((buf2 = strstr(buf,"emi(")) != NULL ){//エミッション格納
sscanf_s(buf2,"emi(%f)",
&Material[Material.size()-1].ReflectionColor.emission);
}
if((buf2 = strstr(buf,"spc(")) != NULL ){//スペキュラー格納
sscanf_s(buf2,"spc(%f)",
&Material[Material.size()-1].ReflectionColor.specular);
}
if((buf2 = strstr(buf,"power(")) != NULL ){//shiness格納
sscanf_s(buf2,"power(%f)", &Material[Material.size()-1].Power);
}
if((buf2 = strstr(buf,"tex(")) != NULL ){//テクスチャ名格納
sscanf_s(buf2,"tex(%[^)])",buf,255);
str=buf;
Material[Material.size()-1].TextureName=Split(&str,'\"','\"');//""を除去
tex.push_back(tex2);
tex[Material.size()-1] = new
TEXTURE(Material[Material.size()-1].TextureName.c_str());
texture.push_back(texture2);
glGenTextures(1, (GLuint *)&texture[Material.size()-1]);
glBindTexture(GL_TEXTURE_2D, texture[Material.size()-1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glEnable(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,tex[Material.size()-1]->Width,
tex[Material.size()-1]->Height,
0,GL_RGBA, GL_UNSIGNED_BYTE, tex[Material.size()-1]->image);
glDisable(GL_TEXTURE_2D);
}
}
}
//頂点情報セット
void MODEL::Vertex_Set(){
int Vertex_Max;
Vector3f v;
fscanf_s(fp, "%d", &Vertex_Max);//頂点数取得
fscanf_s(fp, "%s", buf,255);//"{"を読み飛ばす
for(int i=0;i<Vertex_Max;i++){
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);
Vertex.push_back(v);
}
fscanf_s(fp, "%s", buf,255);//"}"を読み飛ばす
fscanf_s(fp, "%s", buf,255);
}
//面情報セット
void MODEL::Face_Set(){
int Face_Max;
int Face;
Vector3f v;
char* buf2;
fscanf_s(fp, "%d", &Face_Max);//面数取得
fscanf_s(fp, "%s", buf,255);//"{"を読み飛ばす
for(int i=0;i<Face_Max;i++){
fscanf_s(fp, "%d", &Face);
if(Face==3){//3角形
Poly.Polygon=false;
fgets(buf,255,fp);
if((buf2 = strstr(buf,"V(")) != NULL ){
sscanf_s(buf2,"V(%d %d %d)",
&Poly.Index[0],&Poly.Index[1],&Poly.Index[2]);
}
if((buf2 = strstr(buf,"M(")) != NULL ){
sscanf_s(buf2,"M(%d)", &Poly.MaterialID);
}
if((buf2 = strstr(buf,"UV(")) != NULL ){
sscanf_s(buf2,"UV(%f %f %f %f %f %f)",
&Poly.uv[0].u,&Poly.uv[0].v,
&Poly.uv[1].u,&Poly.uv[1].v,&Poly.uv[2].u,&Poly.uv[2].v);
}
for(int i=0;i<3;i++){
v=Vertex[Poly.Index[i]];
Object[Object.size()-1].Group[Poly.MaterialID].TriVer.push_back(v);
Object[Object.size()-1].Group[Poly.MaterialID].TriUV.push_back(Poly.uv[i].u);
Object[Object.size()-1].Group[Poly.MaterialID].TriUV.push_back(Poly.uv[i].v);
}
}
if(Face==4){//4角形
Poly.Polygon=true;
fgets(buf,255,fp);
if((buf2 = strstr(buf,"V(")) != NULL ){
sscanf_s(buf2,"V(%d %d %d %d)",
&Poly.Index[0],&Poly.Index[1],&Poly.Index[2],&Poly.Index[3]);
}
if((buf2 = strstr(buf,"M(")) != NULL ){
sscanf_s(buf2,"M(%d)", &Poly.MaterialID);
}
if((buf2 = strstr(buf,"UV(")) != NULL ){
sscanf_s(buf2,"UV(%f %f %f %f %f %f %f %f)",
&Poly.uv[0].u,&Poly.uv[0].v,
&Poly.uv[1].u,&Poly.uv[1].v,&Poly.uv[2].u,&Poly.uv[2].v,&Poly.uv[3].u,&Poly.uv[3].v);
}
for(int i=0;i<4;i++){
v=Vertex[Poly.Index[i]];
Object[Object.size()-1].Group[Poly.MaterialID].QuadVer.push_back(v);
Object[Object.size()-1].Group[Poly.MaterialID].QuadUV.push_back(Poly.uv[i].u);
Object[Object.size()-1].Group[Poly.MaterialID].QuadUV.push_back(Poly.uv[i].v);
}
}
}
Vertex.clear();
fscanf_s(fp, "%s", buf,255);//"}"を読み飛ばす
fscanf_s(fp, "%s", buf,255);
}
//メタセコイアファイル読み込み
bool MODEL::MQO_Load(char* FileName){
int visible;
if(fopen_s(&fp,FileName, "r")!=0){return false;}
while (!feof(fp)) {
fscanf_s(fp, "%s", buf,255);
if (!strcmp(buf,"Material")){Material_Set();}
if (!strcmp(buf,"Object")){
Object.push_back(obj);
for(int i=0;i<(signed)Material.size();i++){
Object[Object.size()-1].Group.push_back(gro);
if(Material[i].TextureName.length()==0){
Object[Object.size()-1].Group[i].Texture_Use=false;
}else{
Object[Object.size()-1].Group[i].Texture_Use=true;
}
}
fscanf_s(fp, "%s", buf,255);
Object[Object.size()-1].Name=buf;
while (!feof(fp)) {
fscanf_s(fp, "%s", buf,255);
if (!strcmp(buf,"visible")){
fscanf_s(fp, "%d", &visible);
if(visible==0){Object[Object.size()-1].View=false;}else{Object[Object.size()-1].View=true;}
}
if (!strcmp(buf,"vertex")){Vertex_Set();}
if (!strcmp(buf,"face")){Face_Set();}
if (!strcmp(buf,"}"))break;
}
}
}
fclose(fp);
return true;
}
|