#ifndef __CGLMETASEQ_H #define __CGLMETASEQ_H /* メタセコファイル(*.mqo)表示クラス  読み込みはcGLMetaseqParentクラスです。 ・最低限の機能しか実装していないです。 使用方法 ・準備 1)cGLMetaseqParentクラスを作成(ARToolKitの場合,argInit()の後に使用) 2)cGLMetaseqParent::makeGLMetaseqメソッドを使ってcGLMetaseqクラス作成 ・描画方法 1)cGLMetaseq::renderメソッドを呼び出せば描画されます。 ☆読み込んだメタセコファイルの最大値、最小値は以下の方法で取り出せます。 const GLfloat *min = (cGLMetaseqクラス).getMinPoint() ; const GLfloat *max = (cGLMetaseqクラス).getMaxPoint() ; min(max)[0]=x [1]=y [2]=z 使用例:ARToolKitにてメタセコファイルの足をマーカ原点に置きたい場合 const GLfloat *min = (cGLMetaseqクラス).getMinPoint() ; glTranslatef(0,0,min[2]*(-1)) ; (cGLMetaseqクラス).render() ; メタセコフォーマットはこちら。 http://www.metaseq.net/metaseq/format.html code by kei */ #ifdef _WIN32 #include #endif #include #include #include #ifndef __APPLE__ #include #include #include #else #include #include #include #endif #include "texturePool.h" #include "endianConverter.h" #include "WinGlExtensions.h" #include class cGLMetaseq { private : friend class cGLMetaseqParent; //表示用 typedef struct { GLfloat point[3]; // 頂点配列 (x, y, z) GLfloat normal[3]; // 法線配列 (x, y, z) GLfloat uv[2]; // UV配列 (u, v) } VERTEX_TEXUSE; typedef struct { GLfloat point[3]; // 頂点配列 (x, y, z) GLfloat normal[3]; // 法線配列 (x, y, z) } VERTEX_NOTEX; typedef struct { bool isValidMaterialInfo;// マテリアル情報の有効/無効 bool isUseTexture; // テクスチャの有無:USE_TEXTURE / NOUSE_TEXTURE GLuint texture_id; // テクスチャの名前(OpenGL) GLuint VBO_id; // 頂点バッファのID(OpenGL) 対応してる時だけ使用 int datanum; // 頂点数 GLfloat color[4]; // 色配列 (r, g, b, a) GLfloat dif[4]; // 拡散光 GLfloat amb[4]; // 周囲光 GLfloat emi[4]; // 自己照明 GLfloat spc[4]; // 反射光 GLfloat power; // 反射光の強さ VERTEX_NOTEX *vertex_p; // ポリゴンのみの時の頂点配列 VERTEX_TEXUSE *vertex_t; // テクスチャ使用時の頂点配列 } MQO_MATERIAL; typedef struct { char objname[256]; // オブジェクト名(仕様に文字数の規定なし) bool isVisible; // 0:非表示 その他:表示 bool isShadingFlat ; // シェーディングモード GLfloat minPoint[3]; // 頂点 (x, y, z) GLfloat maxPoint[3]; // 頂点 (x, y, z) vector mat; // マテリアル配列 } MQO_INNER_OBJECT; typedef struct { unsigned char alpha; // 頂点配列作成時に指定されたアルファ値(参照用) GLfloat minPoint[3]; // 頂点 (x, y, z) GLfloat maxPoint[3]; // 頂点 (x, y, z) vector obj; // 内部オブジェクト配列 } MQO_OBJECT; typedef struct { GLfloat minPoint[3]; // 頂点 (x, y, z) GLfloat maxPoint[3]; // 頂点 (x, y, z) vector model; // モデル } MQO_SEQUENCE; MQO_SEQUENCE m_seq ; cGLMetaseq(MQO_OBJECT *data) { m_seq.minPoint[0] = data->minPoint[0] ; m_seq.minPoint[1] = data->minPoint[1] ; m_seq.minPoint[2] = data->minPoint[2] ; m_seq.maxPoint[0] = data->maxPoint[0] ; m_seq.maxPoint[1] = data->maxPoint[1] ; m_seq.maxPoint[2] = data->maxPoint[2] ; m_seq.model.push_back(data) ; } void push_back(MQO_OBJECT *data) { for( int xyz = 0 ; xyz < 3 ; xyz++ ) { if( data->minPoint[xyz] < m_seq.minPoint[xyz] ) m_seq.minPoint[xyz] = data->minPoint[xyz] ; if( m_seq.maxPoint[xyz] < data->maxPoint[xyz] ) m_seq.maxPoint[xyz] = data->maxPoint[xyz] ; } m_seq.model.push_back(data) ; } public : virtual ~cGLMetaseq() { size_t s,s_num ; size_t i,i_num ; size_t m,m_num ; MQO_OBJECT *obj ; MQO_INNER_OBJECT *inner ; vector::iterator inner_it ; vector::iterator obj_it ; s_num = m_seq.model.size() ; for( s = 0 ; s < s_num ; s++ ) { obj = m_seq.model.at(s) ; i_num = obj->obj.size() ; for( i = 0 ; i < i_num ; i++ ) { inner = obj->obj.at(i) ; m_num = inner->mat.size() ; for( m = 0 ; m < m_num ; m++ ) { MQO_MATERIAL &mat = inner->mat.at(m) ; if( mat.vertex_p != NULL ) free(mat.vertex_p) ; if( mat.vertex_t != NULL ) free(mat.vertex_t) ; if( mat.VBO_id != 0 ) glDeleteBuffersARB(1,&mat.VBO_id) ; } delete inner ; } delete obj ; } } public : //読み込んだデータの最小値(x、y、z)を取り出す // in frame フレーム番号 負だと全フレームの最小値 // 戻り値 GLfloat[3] 0〜2 がそれぞれx、y、z const GLfloat *getMinPoint(int frame=-1) { if( frame < 0 ) { return m_seq.minPoint ; } if( frame < (int)m_seq.model.size() ) { return m_seq.model.at(frame)->minPoint ; } return NULL ; } //読み込んだデータの最大値(x、y、z)を取り出す // in frame フレーム番号 負だと全フレームの最大値 // 戻り値 GLfloat[3] 0〜2 がそれぞれx、y、z const GLfloat *getMaxPoint(int frame=-1) { if( frame < 0 ) { return m_seq.maxPoint ; } if( frame < (int)m_seq.model.size() ) { return m_seq.model.at(frame)->maxPoint ; } return NULL ; } //読み込んでいるフレーム数を取り出す // 戻り値 size_t フレーム数 size_t getFrameNum() { return m_seq.model.size() ; } //読み込んでいるモデルの描画 // in frame 描画するフレーム番号(0〜) // in alpha 透明度(0(透明)〜255) void render(int frame = 0,unsigned char alpha=0xff) { if( m_seq.model.size() <= (unsigned int)frame ) return ; MQO_OBJECT *sobj ; MQO_INNER_OBJECT *obj; GLfloat matenv[4] ; GLfloat matenvGL_DIFFUSE[4] ; GLfloat matenvGL_AMBIENT[4] ; GLfloat matenvGL_SPECULAR[4] ; GLfloat matenvGL_EMISSION[4] ; GLfloat matenvGL_SHININESS ; GLboolean isGL_ALPHA_TEST = GL_FALSE ; GLboolean isGL_DEPTH_TEST = GL_FALSE ; GLint bindGL_TEXTURE_2D = 0 ; GLboolean isGL_TEXTURE_2D = GL_FALSE ; GLboolean isGL_BLEND = GL_FALSE ; GLint blendGL_SRC ; GLint blendGL_DST ; GLint enumGL_SHADE_MODEL ; //メタセコは頂点の並びが表面からみて右回り GLint intFrontFace ; int offset; double dalpha; char *base; size_t o,o_num ; size_t m,m_num ; //変更パラメータの保存 isGL_DEPTH_TEST = glIsEnabled(GL_DEPTH_TEST) ; isGL_ALPHA_TEST = glIsEnabled(GL_ALPHA_TEST) ; glGetIntegerv(GL_FRONT_FACE,&intFrontFace) ; glGetIntegerv(GL_SHADE_MODEL,&enumGL_SHADE_MODEL) ; isGL_TEXTURE_2D = glIsEnabled(GL_TEXTURE_2D) ; isGL_BLEND = glIsEnabled(GL_BLEND) ; glGetIntegerv(GL_TEXTURE_BINDING_2D,&bindGL_TEXTURE_2D) ; glGetIntegerv(GL_BLEND_SRC,&blendGL_SRC) ; glGetIntegerv(GL_BLEND_DST,&blendGL_DST) ; glGetMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,matenvGL_DIFFUSE) ; glGetMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,matenvGL_AMBIENT) ; glGetMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,matenvGL_SPECULAR) ; glGetMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,matenvGL_EMISSION) ; glGetMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS,&matenvGL_SHININESS) ; sobj = m_seq.model.at(frame) ; glPushMatrix(); if( isGL_DEPTH_TEST == GL_FALSE ) { glEnable(GL_DEPTH_TEST); } if( isGL_ALPHA_TEST == GL_FALSE ) { glEnable(GL_ALPHA_TEST); } //メタセコは頂点の並びが表面からみて右回り glFrontFace(GL_CW) ; dalpha = (double)alpha/(double)255; o_num = sobj->obj.size() ; for ( o=0; oobj.at(o) ; m_num = obj->mat.size() ; // obj = &mqoobj[num].obj[o]; if ( ! obj->isVisible ) continue; glShadeModel(((obj->isShadingFlat))?GL_FLAT:GL_SMOOTH) ; for ( m = 0; m < m_num; m++ ) { //マテリアルループ MQO_MATERIAL &mat = obj->mat.at(m) ; // mat = &obj->mat[m]; if ( mat.datanum == 0 ) continue; if ( mat.isValidMaterialInfo ) { // マテリアルの情報設定 // ☆透明度の変更しないなら、この変更は要らないか… memcpy(matenv,mat.dif,sizeof(matenv)) ; matenv[3] *= dalpha ; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matenv); memcpy(matenv,mat.amb,sizeof(matenv)) ; matenv[3] *= dalpha ; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matenv); memcpy(matenv,mat.spc,sizeof(matenv)) ; matenv[3] *= dalpha ; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matenv); memcpy(matenv,mat.emi,sizeof(matenv)) ; matenv[3] *= dalpha ; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matenv); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat.power); } if ( mat.isUseTexture) { // テクスチャがある場合 glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D,mat.texture_id); if ( mat.VBO_id != 0 ) { // 頂点バッファ使用 base = (char *)NULL; // アドレスはNULLが先頭 glBindBufferARB( GL_ARRAY_BUFFER_ARB, mat.VBO_id ); // 頂点バッファを結びつける } else { // 頂点配列の時は、アドレスをそのまま入れる base = (char *)mat.vertex_t[0].point; } // 頂点配列を設定 offset = (int)( (char *)mat.vertex_t[0].point - (char *)mat.vertex_t[0].point ); glVertexPointer( 3, GL_FLOAT, sizeof(VERTEX_TEXUSE) , base + offset ); // テクスチャ座標配列を設定 offset = (int)((char *)mat.vertex_t[0].uv-(char *)mat.vertex_t[0].point); glTexCoordPointer( 2, GL_FLOAT, sizeof(VERTEX_TEXUSE) , base + offset ); // 法線配列を設定 offset = (int)((char *)mat.vertex_t[0].normal-(char *)mat.vertex_t[0].point); glNormalPointer( GL_FLOAT, sizeof(VERTEX_TEXUSE) , base+offset ); // 色設定 glColor4f(mat.color[0],mat.color[1],mat.color[2],mat.color[3]); // 描画実行 glDrawArrays( GL_TRIANGLES, 0, mat.datanum ); if ( mat.VBO_id != 0 ) { // 頂点バッファ使用 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); // 頂点バッファをデフォルトへ } glBindTexture(GL_TEXTURE_2D,0); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); } else { // テクスチャがない場合 glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); // glEnableClientState( GL_COLOR_ARRAY ); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); if ( mat.VBO_id != 0 ) { // 頂点バッファ使用 base = (char *)NULL; glBindBufferARB( GL_ARRAY_BUFFER_ARB, mat.VBO_id ); } else { base = (char *)mat.vertex_p[0].point; } // 頂点配列を設定 offset = (int)((char *)mat.vertex_p[0].point-(char *)mat.vertex_p[0].point); glVertexPointer( 3, GL_FLOAT, sizeof(VERTEX_NOTEX) , base+offset ); // 法線配列を設定 offset = (int)((char *)mat.vertex_p[0].normal-(char *)mat.vertex_p[0].point); glNormalPointer( GL_FLOAT, sizeof(VERTEX_NOTEX) , base+offset ); // 色設定 glColor4f(mat.color[0],mat.color[1],mat.color[2],mat.color[3]); // offset = (int)((char *)mat.vertex_p[0].color-(char *)mat.vertex_p[0].point); // glColorPointer(4,GL_FLOAT,sizeof(VERTEX_NOTEX),base+offset); // 描画実行 glDrawArrays( GL_TRIANGLES, 0, mat.datanum ); if ( mat.VBO_id != 0 ) { // 頂点バッファ使用 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); // 頂点バッファをデフォルトへ } // glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); } } } //変更パラメータの復帰 glShadeModel(enumGL_SHADE_MODEL) ; glBindTexture(GL_TEXTURE_2D,bindGL_TEXTURE_2D); glBlendFunc(blendGL_SRC,blendGL_DST); if( isGL_BLEND == GL_FALSE ) glDisable(GL_BLEND); if( isGL_TEXTURE_2D == GL_FALSE ) glDisable(GL_TEXTURE_2D); glFrontFace(intFrontFace) ; if( isGL_DEPTH_TEST == GL_FALSE ) { glDisable(GL_DEPTH_TEST); } if( isGL_ALPHA_TEST == GL_FALSE ) { glDisable(GL_ALPHA_TEST); } glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,matenvGL_DIFFUSE) ; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,matenvGL_AMBIENT) ; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,matenvGL_SPECULAR) ; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,matenvGL_EMISSION) ; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,matenvGL_SHININESS) ; glPopMatrix(); } }; #include "cGLMetaseqParent.h" #endif