最終更新: mikk_ni3_92 2010年02月04日(木) 18:38:08履歴
現在地: メニュー >> 実践編10 >> 実践編10::3dsファイルローダ >> lib3ds編04
INDEX: lib3ds編03 << lib3ds編04 >> lib3ds編05?
材質データは「Lib3dsFile構造体」のメンバ「int nmaterials」が設定されているマテリアルの数を示す。
具体的なデータは「Lib3dsFile構造体」→「Lib3dsMaterial構造体」の中にある。
そのなかのメンバには
材質データを取り出す時は次のような感じ。
【解説】
モデルによっては、材質そのものを設定していないものもある。
そのような場合は「retrun」等して処理をカット。
「GLC-Player」で確認したところ、shinness = 0.01fの時は、「shinnessに20.0を設定する」といい。
その他の時には128をかけてスケール変換しておく。「glMaterial関数」に渡すため。
OpenGLの材質のアルファ値は、diffuseのみが計算に使用されるので、他は「1」でよい。
INDEX: lib3ds編03 << lib3ds編04 >> lib3ds編05?
材質データは「Lib3dsFile構造体」のメンバ「int nmaterials」が設定されているマテリアルの数を示す。
具体的なデータは「Lib3dsFile構造体」→「Lib3dsMaterial構造体」の中にある。
そのなかのメンバには
- char name[64]:材質の名前
- float ambient[3]:環境光
- float diffuse[3]:拡散光
- float specular[3]:スペキュラ光
- float shininess:輝度係数
- float transparency:透明度(「1-transparency」でdiffuseのアルファ値)
材質データを取り出す時は次のような感じ。
Lib3dsFile *m_model; Lib3dsMesh *mesh; … … //データ構造 struct Materials { float ambient[4]; float diffuse[4]; float specular[4]; float shininess; }; std::vector<Materials> materials; … … //マテリアルが無い場合は終了 if(m_model->nmaterials == 0) { return -1; } //マテリアルデータの取り出し Lib3dsMaterial *material; //メモリ確保 materials.resize(m_model->nmaterials); for(int loop = 0; loop < m_model->nmaterials;++loop) { material= m_model->materials[loop];//loop番目のマテリアル std::cout << material->name << " - ";//マテリアル名 //ambient memcpy(materials[loop].ambient, material->ambient, sizeof(material->ambient) ); materials[loop].ambient[3] = 1; //diffuse memcpy(materials[loop].diffuse, material->diffuse, sizeof(material->diffuse) ); materials[loop].diffuse[3] =1 - material->transparency; //shinness memcpy(&materials[loop].shininess, &material->shininess, sizeof(material->shininess) ); if ( materials[loop].shininess == 0.01f) { materials[loop].shininess = 20.f; }else { materials[loop].shininess *= 128; } //specular memcpy(materials[loop].specular,material->specular,sizeof(material->specular) ); materials[loop].specular[3]=1; }
【解説】
モデルによっては、材質そのものを設定していないものもある。
そのような場合は「retrun」等して処理をカット。
「GLC-Player」で確認したところ、shinness = 0.01fの時は、「shinnessに20.0を設定する」といい。
その他の時には128をかけてスケール変換しておく。「glMaterial関数」に渡すため。
OpenGLの材質のアルファ値は、diffuseのみが計算に使用されるので、他は「1」でよい。
マテリアルの情報は面単位で持っている。
すなわち、
「Lib3dsFile構造体」→「Lib3dsMesh構造体」→「Lib3dsFace構造体」のメンバ「int material」
に何番目のマテリアルを適用するのかという情報が格納されている。
すなわち、
「Lib3dsFile構造体」→「Lib3dsMesh構造体」→「Lib3dsFace構造体」のメンバ「int material」
に何番目のマテリアルを適用するのかという情報が格納されている。
Lib3dsFile *m_model; Lib3dsMesh *mesh; int materialId;//マテリアルの管理用(材質が無い場合は-999が入っているものとする) … … //メッシュ単位でのループ for(int mLoop = 0; mLoop < m_model->nmeshes;++mLoop) { mesh = m_model->meshes[mLoop];//mLoop番目のメッシュへのポインタ //面単位でのループ for(int loopX = 0;loopX < mesh->nfaces;++loopX) { //マテリアル設定が全くない場合はカット if(materialId != -999){ materialId = mesh->faces[loopX].material;//Id取得 if(materialId >=0){ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materials[ materialId ].ambient); //面がもつ材質IDを指定する glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materials[ materialId ].diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materials[ materialId ].specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, materials[ materialId ].shininess); }else { /*マテリアル設定がない時は適当に設定*/ } } … … } }
「Lib3dsFile構造体」→「Lib3dsMesh構造体」→「Lib3dsFace構造体」のメンバ「int material」が「−1」の時は、
材質設定が行われていない。
たぶんテクスチャマッピングだけをしている。
材質設定が行われていない。
たぶんテクスチャマッピングだけをしている。
glBegin/glEndだとこんな感じ
【例】
【例】
Lib3dsFile *m_model; Lib3dsMesh *mesh; //法線格納場所 struct MeshNormal { float (*vertnormals)[3]; }; std::vector<MeshNormal> meshNormalAry; //材質データ格納用 struct Materials { float ambient[4]; float diffuse[4]; float specular[4]; float shininess; }; std::vector<Materials> materials; //デフォルト材質 Materials MatDefault= { {0.2f, 0.2f, 0.2f, 1.f}, {0.8f, 0.8f, 0.8f, 1.f}, {0.f, 0.f, 0.f, 1.f}, 0.f }; int materialId;//マテリアルの管理用 … … //メッシュ単位でのループ for(int mLoop = 0; mLoop < m_model->nmeshes;++mLoop) { mesh = m_model->meshes[mLoop];//mLoop番目のメッシュへのポインタ //面単位でのループ for(int loopX = 0;loopX < mesh->nfaces;++loopX) { //マテリアル設定が全くない場合はカット if(materialId != -999){ materialId = mesh->faces[loopX].material; if(materialId >=0){ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materials[ materialId ].ambient); //面がもつ材質IDを指定する glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materials[ materialId ].diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materials[ materialId ].specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, materials[ materialId ].shininess); }else { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MatDefault.ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MatDefault.diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatDefault.specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MatDefault.shininess); } } glBegin(GL_TRIANGLES); //1頂点目 glNormal3f( meshNormalAry[mLoop].vertnormals[loopX*3][0], meshNormalAry[mLoop].vertnormals[loopX*3][1], meshNormalAry[mLoop].vertnormals[loopX*3][2]); glVertex3f( mesh->vertices[ mesh->faces[loopX].index[0] ][0], mesh->vertices[ mesh->faces[loopX].index[0] ][1], mesh->vertices[ mesh->faces[loopX].index[0] ][2]); //2頂点目 glNormal3f( meshNormalAry[mLoop].vertnormals[loopX*3+1][0], meshNormalAry[mLoop].vertnormals[loopX*3+1][1], meshNormalAry[mLoop].vertnormals[loopX*3+1][2]); glVertex3f( mesh->vertices[ mesh->faces[loopX].index[1] ][0], mesh->vertices[ mesh->faces[loopX].index[1] ][1], mesh->vertices[ mesh->faces[loopX].index[1] ][2]); //3頂点目 glNormal3f( meshNormalAry[mLoop].vertnormals[loopX*3+2][0], meshNormalAry[mLoop].vertnormals[loopX*3+2][1], meshNormalAry[mLoop].vertnormals[loopX*3+2][2]); glVertex3f( mesh->vertices[ mesh->faces[loopX].index[2] ][0], mesh->vertices[ mesh->faces[loopX].index[2] ][1], mesh->vertices[ mesh->faces[loopX].index[2] ][2]); glEnd(); } }