#pragma once
#pragma comment(lib,"fbxsdk_20113.lib")
#define K_PLUGIN
#define K_FBXSDK
#define K_NODLL
#define KFBX_DLLINFO
#include "PNG.h"
#include <fbxsdk.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;
//モデルクラス
class MODEL{
protected:
vector <MATERIAL> Material;//マテリアル
vector <TEXTURE*> TexData;//テクスチャデータ
vector<GLuint> TexID;//テクスチャID
GLuint TexID2;//代入用
TEXTURE* tex;//代入用
public:
KFbxSdkManager *SdkManager;//FBXSDKマネージャー
KFbxImporter* Importer;
KFbxScene* Scene;
KFbxNode* pRootNode;
MODEL();
MODEL(char* FileName,float size);//コンストラクタ
bool FBX_Load(char* FileName,float size);//ロード
bool MESH_Get(int NO,float size);
void Draw();
};
MODEL::MODEL(){
}
MODEL::MODEL(char* FileName,float size){
FBX_Load(FileName, size);
}
//描画
void MODEL::Draw(){
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
for(int i=0;i<(signed)Material.size();i++){
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(const GLfloat
*)&Material[i].MaterialColor.ambient);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(const GLfloat
*)&Material[i].MaterialColor.diffuse);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat
*)&Material[i].MaterialColor.specular);
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,Material[i].Shininess);
if(Material[i].TexNo>0){
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexID[Material[i].TexNo-1]);
}else{
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if(Material[i].Tridata.size()>1){
glVertexPointer(3, GL_FLOAT,sizeof(Tri) ,
&Material[i].Tridata[0].TriVer.x);
glNormalPointer(GL_FLOAT,sizeof(Tri),&Material[i].Tridata[0].TriNor.x);
if(Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Tri),
&Material[i].Tridata[0].TriUV.u);
glDrawArrays(GL_TRIANGLES,0,Material[i].Tridata.size());
}
if(Material[i].Quaddata.size()>1){
glVertexPointer(3, GL_FLOAT,sizeof(Quad) ,
&Material[i].Quaddata[0].QuadVer.x);
glNormalPointer(GL_FLOAT,sizeof(Quad),&Material[i].Quaddata[0].QuadNor.x);
if(Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Quad),
&Material[i].Quaddata[0].QuadUV.u);
glDrawArrays(GL_QUADS,0,Material[i].Quaddata.size());
}
glPopMatrix();
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
//FBXファイル読み込み
bool MODEL::FBX_Load(char* FileName,float size){
SdkManager = KFbxSdkManager::Create();
Importer=KFbxImporter::Create(SdkManager,"importer");
Importer->Initialize((const char*)FileName,-1);
Scene = KFbxScene::Create(SdkManager, "scene");
Importer->Import(Scene);
pRootNode=Scene->GetRootNode();//ノード
for(int i=0;i<pRootNode->GetChildCount();i++){
MESH_Get(i,size);
}
return true;
}
bool MODEL::MESH_Get(int NO,float size){
vector <Vector3f> Vertex;//頂点
vector <Vector3f> Normal;//法線
vector <UV> uv;//UV
vector <int> VertexIndex;
KFbxMesh* pFbxMesh=0;
KFbxNodeAttribute::EAttributeType type;
KFbxNodeAttribute *pAttr=pRootNode->GetNodeAttribute();
int iNumChild=pRootNode->GetChildCount();
KFbxNode* pChildNode=pRootNode->GetChild(NO);
if(pAttr!=NULL)
{
type=pAttr->GetAttributeType();
if(type==KFbxNodeAttribute::eMESH)//タイプがメッシュの場合
{
pFbxMesh=pRootNode->GetMesh();
}
}
else//子がメッシュの可能性あり
{
pAttr=pChildNode->GetNodeAttribute();
type=pAttr->GetAttributeType();
if(type==KFbxNodeAttribute::eMESH)//タイプがメッシュの場合
{
pFbxMesh=pChildNode->GetMesh();
}
else
{
MessageBox(0,L"メッシュの読み込み失敗",NULL,MB_OK);
}
}
//頂点読み込み
KFbxVector4* pCoord=pFbxMesh->GetControlPoints();
for(int i=0;i<pFbxMesh->GetControlPointsCount();i++)
{
vec3d.x=(float)pCoord[i][0]*size;
vec3d.y=(float)pCoord[i][1]*size;
vec3d.z=(float)pCoord[i][2]*size;
Vertex.push_back(vec3d);
}
//法線読み込み
KFbxLayerElementNormal* ElementNormal =
pFbxMesh->GetLayer(0)->GetNormals();
if ( ElementNormal->GetMappingMode() ==
KFbxLayerElement::eBY_POLYGON_VERTEX ) {
if ( ElementNormal->GetReferenceMode() == KFbxLayerElement::eDIRECT )
{
// 直接取得
for ( int i = 0; i < ElementNormal->GetDirectArray().GetCount(); ++i )
{
vec3d.x = (float)ElementNormal->GetDirectArray().GetAt( i )[ 0 ];
vec3d.y = (float)ElementNormal->GetDirectArray().GetAt( i )[ 1 ];
vec3d.z = (float)ElementNormal->GetDirectArray().GetAt( i )[ 2 ];
Normal.push_back(vec3d);
}
}
}else if( ElementNormal->GetMappingMode() ==
KFbxLayerElement::eBY_CONTROL_POINT ) {
if ( ElementNormal->GetReferenceMode() == KFbxLayerElement::eDIRECT )
{
// 直接取得
for ( int i = 0; i < ElementNormal->GetDirectArray().GetCount(); ++i )
{
vec3d.x = (float)ElementNormal->GetDirectArray().GetAt( i )[ 0 ];
vec3d.y = (float)ElementNormal->GetDirectArray().GetAt( i )[ 1 ];
vec3d.z = (float)ElementNormal->GetDirectArray().GetAt( i )[ 2 ];
Normal.push_back(vec3d);
}
}
}
//テクスチャー座標読み込み
KFbxLayerElementUV* pUV=pFbxMesh->GetLayer(0)->GetUVs();
int uvsize = pUV->GetDirectArray().GetCount() >
pUV->GetIndexArray().GetCount() ? pUV->GetDirectArray().GetCount() :
pUV->GetIndexArray().GetCount();
if ( pUV->GetMappingMode() == KFbxLayerElement::eBY_POLYGON_VERTEX )
{
if ( pUV->GetReferenceMode() == KFbxLayerElement::eDIRECT ) {
// 直接取得
for ( int i = 0; i < uvsize; ++i ) {
KFbxVector2 v2;
uv.push_back(vec2d);
uv[i].u = (float)pUV->GetDirectArray().GetAt( i )[ 0 ];
uv[i].v = 1.0f-(float)pUV->GetDirectArray().GetAt( i )[ 1 ];
}
}else if ( pUV->GetReferenceMode() == KFbxLayerElement::eINDEX_TO_DIRECT )
{
// インデックスから取得
for ( int i = 0; i < uvsize; ++i ) {
KFbxVector2 v2;
uv.push_back(vec2d);
int index = pUV->GetIndexArray().GetAt( i );
uv[i].u = (float)pUV->GetDirectArray().GetAt( index )[ 0 ];
uv[i].v = 1.0f-(float)pUV->GetDirectArray().GetAt( index )[ 1 ];
}
}
}
//マテリアル読み込み
KFbxNode* pNode=pFbxMesh->GetNode();
for(int i=0;i<pNode->GetMaterialCount();i++)
{
//フォンモデルを想定
KFbxSurfaceMaterial* pMaterial=pNode->GetMaterial(i);
KFbxSurfacePhong* pPhong=(KFbxSurfacePhong*)pMaterial;
//環境光
KFbxPropertyDouble3 d3Ambient=pPhong->GetAmbientColor();
mtl.MaterialColor.ambient.r=(float)d3Ambient.Get()[0];
mtl.MaterialColor.ambient.g=(float)d3Ambient.Get()[1];
mtl.MaterialColor.ambient.b=(float)d3Ambient.Get()[2];
mtl.MaterialColor.ambient.a=1.0f;
//拡散反射光
KFbxPropertyDouble3 d3Diffuse=pPhong->GetDiffuseColor();
mtl.MaterialColor.diffuse.r=(float)d3Diffuse.Get()[0];
mtl.MaterialColor.diffuse.g=(float)d3Diffuse.Get()[1];
mtl.MaterialColor.diffuse.b=(float)d3Diffuse.Get()[2];
mtl.MaterialColor.diffuse.a=1.0f;
//鏡面反射光
KFbxPropertyDouble3 d3Specular=pPhong->GetDiffuseColor();
mtl.MaterialColor.specular.r=(float)d3Specular.Get()[0];
mtl.MaterialColor.specular.g=(float)d3Specular.Get()[1];
mtl.MaterialColor.specular.b=(float)d3Specular.Get()[2];
mtl.MaterialColor.specular.a=1.0f;
mtl.Shininess= (float)pPhong->GetShininess().Get();
//テクスチャ
KFbxProperty
lProperty=pMaterial->FindProperty(KFbxSurfaceMaterial::sDiffuse);
KFbxTexture*
ktex=KFbxCast<KFbxTexture>(lProperty.GetSrcObject(KFbxTexture::ClassId,
0));
if(ktex)
{
mtl.TextureName=ktex->GetFileName();
//テクスチャを作成
TexData.push_back(tex);
TexData[TexData.size()-1] = new TEXTURE(mtl.TextureName.c_str());;
mtl.TexNo=TexData.size();
TexID.push_back(TexID2);
glGenTextures(1, (GLuint *)&TexID[TexData.size()-1]);
glBindTexture(GL_TEXTURE_2D, TexID[TexData.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,TexData[TexData.size()-1]->Width,
TexData[TexData.size()-1]->Height,
0,GL_RGBA, GL_UNSIGNED_BYTE, TexData[TexData.size()-1]->image);
glDisable(GL_TEXTURE_2D);
}
Material.push_back(mtl);
}
int count=0;
//マテリアル毎のデータを作成
for(int k=0;k<pFbxMesh->GetPolygonCount();k++)
{
KFbxLayerElementMaterial* mat =
pFbxMesh->GetLayer(0)->GetMaterials();//レイヤーが1枚だけを想定
int matId=mat->GetIndexArray().GetAt(k);
if(pFbxMesh->GetPolygonSize( k )==3){
for(int j=0;j<3;j++){
Tri.TriVer=Vertex[pFbxMesh->GetPolygonVertex( k, j )];
Tri.TriNor=Normal[count+j];
Tri.TriUV=uv[count+j];
Material[matId].Tridata.push_back(Tri);
}
count+=3;
}
if(pFbxMesh->GetPolygonSize( k )==4){
for(int j=0;j<4;j++){
Quad.QuadVer=Vertex[pFbxMesh->GetPolygonVertex( k, j )];
Quad.QuadNor=Normal[count+j];
Quad.QuadUV=uv[count+j];
Material[matId].Quaddata.push_back(Quad);
}
count+=4;
}
}
Vertex.clear();
Normal.clear();
uv.clear();
VertexIndex.clear();
return true;
}
|