#ifndef __CGLMETASEQPARENT_H #define __CGLMETASEQPARENT_H /* メタセコファイル(*.mqo)読み込みクラス  表示はcGLMetaseqクラスです。 ・最低限の機能しか実装していないです。 使用方法 ・準備 1)cGLMetaseqParentクラスを作成(ARToolKitの場合,argInit()の後に使用) 2)cGLMetaseqParent::makeGLMetaseqメソッドを使ってcGLMetaseqクラス作成 読み込みはmakeGLMetaseqで行っている。 ・1ファイル読み込みと表示クラス作成メソッド cGLMetaseq *makeGLMetaseq( char *filename, ←ファイル名 PFNMETASEQTRANSANDSCALEPROC transproc, ←座標変換ルーチン(NULL可) float scale=1.0) ←読み込みスケール 例:data/model.mqoファイルをARToolKit用に読み込む (cGLMetaseqParentクラス).makeGLMetaseq( "data/model.mqo", cGLMetaseqParent::forARToolKit) ; ・連番ファイルの読み込みと表示クラス作成メソッド cGLMetaseq *makeGLMetaseq( char *basename, ←ベースファイル名 char *format, ←フォーマット int start, ←読み込み開始番号 int end, ←読み込み終了番号 PFNMETASEQTRANSANDSCALEPROC transproc, ←座標変換ルーチン(NULL可) float scale=1.0) ←読み込みスケール 連番ファイルの形式 RokDeBone2 %s%d.mqo mikoto %s%04d.mqo 例:data/model0.mqo〜model9.mqo ファイルを読み込む (cGLMetaseqParentクラス).makeGLMetaseq( "data/model", DEF_MQO_FORMAT_ROCKDEBONE2, 0, 9, NULL) ; メタセコフォーマットはこちら。 http://www.metaseq.net/metaseq/format.html code by kei */ #include "cGLMetaseq.h" typedef void (APIENTRY * PFNMETASEQTRANSANDSCALEPROC) (float *x,float *y,float *z); #define DEF_MQO_FORMAT_ROCKDEBONE2 "%s%d.mqo" #define DEF_MQO_FORMAT_MIKOTO "%s%04d.mqo" class cGLMetaseqParent { public : //ARToolKit用座標変換 // OpenGL座標系 //    Y //    | //    | //    +------X //   / //  / //  Z // // ARToolKit座標系 //    Z //    |  Y //    | / //    |/ //    +------X //ARToolKitでマーカはx−y平面 static void APIENTRY forARToolKit (float *x,float *y,float *z){ float w ; w = *y ; *y = *z * (-1) ; *z = w ; } private : bool m_isVBOSupported ; bool m_isTexPoolMaking ; texturePool *m_texPool ; //読み込み用 typedef struct { GLfloat x; GLfloat y; } glPOINT2f; typedef struct { GLfloat x; GLfloat y; GLfloat z; } glPOINT3f; typedef struct { int m; // 面の材質番号 int v[3]; // 頂点番号を格納した配列 glPOINT2f uv[3]; // UVマップ } MQO_FACE; typedef struct { GLfloat col[4]; // 色 GLfloat dif[4]; // 拡散光 GLfloat amb[4]; // 周囲光 GLfloat emi[4]; // 自己照明 GLfloat spc[4]; // 反射光 GLfloat power; // 反射光の強さ bool useTex; // テクスチャの有無 char texFile[64]; // テクスチャファイル char alpFile[64]; // アルファテクスチャファイル GLuint texName; // テクスチャ名 } MQO_MATDATA; //Materialチャンク typedef struct { char objname[256]; // パーツ名(仕様に文字数の規定なし) int visible; // 可視状態 int shading; // シェーディング(0:フラット/1:グロー) float facet; // スムージング角 int n_vertex; // 頂点数 vector F; // 面 glPOINT3f *V; // 頂点 } MQO_OBJDATA; //Objectチャンク int MAX(int a,int b) { return (a>b)?a:b ; } char * MAX(char * a,char * b) { return (a>b)?a:b ; } public : //コンストラクタ // in texPool テクスチャ管理クラス。NULLなら内部用に作成する。 cGLMetaseqParent(texturePool *texPool = NULL) { if( texPool == NULL ) { m_texPool = new texturePool() ; m_isTexPoolMaking = true ; } else { m_texPool = texPool ; m_isTexPoolMaking = false ; } m_isVBOSupported = (glutExtensionSupported("GL_ARB_vertex_buffer_object")!=0); #ifdef WIN32 if( m_isVBOSupported ) { if( glGenBuffersARB == NULL ) glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB"); if( glBindBufferARB == NULL ) glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB"); if( glBufferDataARB == NULL ) glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB"); if( glDeleteBuffersARB == NULL ) glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB"); } #endif } virtual ~cGLMetaseqParent() { if( m_isTexPoolMaking ) delete m_texPool ; } //1ファイル読み込みと表示クラス作成 // in filename 読み込みファイル名 // in transproc 座標変換ルーチン(NULL可) // in scale 読み込み倍率 // 戻り値 表示クラス cGLMetaseq *makeGLMetaseq( char *filename, PFNMETASEQTRANSANDSCALEPROC transproc,float scale=1.0) { cGLMetaseq::MQO_OBJECT * data ; data = loadFile(filename,transproc,scale) ; if( data == NULL ) return NULL ; return new cGLMetaseq(data) ; } //連番ファイルの読み込みと表示クラス作成 // in basename ベースファイル名 // in format 読み込みファイルフォーマット // in start 読み込み開始番号 // in end 読み込み終了番号 // in step 読み込み番号の間隔(1で全部読む) // in transproc 座標変換ルーチン(NULL可) // in scale 読み込み倍率 // 戻り値 表示クラス cGLMetaseq *makeGLMetaseq( char *basename, char *format,int start,int end,int step, PFNMETASEQTRANSANDSCALEPROC transproc,float scale=1.0) { char filename[256] ; cGLMetaseq::MQO_OBJECT * data ; cGLMetaseq *ret = NULL ; int n ; for( n = start ; n <= end ; n+=step ) { sprintf(filename,format,basename,n) ; data = loadFile(filename,transproc,scale) ; if( data == NULL ) continue ; if( ret == NULL ) { ret = new cGLMetaseq(data) ; if( ret == NULL ) break ; continue ; } ret->push_back(data) ; } return ret ; } private : /* cGLMetaseq::MQO_OBJECT *loadFile(char *filename, PFNMETASEQTRANSANDSCALEPROC transproc,float scale, unsigned char alpha) ; void readMaterial(FILE *fp, MQO_MATDATA M[]) ; void readVertex(FILE *fp, glPOINT3f V[],PFNMETASEQTRANSANDSCALEPROC transproc,float scale); int readBVertex(FILE *fp, glPOINT3f V[],PFNMETASEQTRANSANDSCALEPROC transproc,float scale); void readFace(FILE *fp,MQO_OBJDATA *obj); void readObject(FILE *fp, MQO_OBJDATA *obj,PFNMETASEQTRANSANDSCALEPROC transproc,float scale); void snormal(glPOINT3f A, glPOINT3f B, glPOINT3f C, glPOINT3f *normal) ; glPOINT3f *vertexNormal(MQO_OBJDATA *obj) ; cGLMetaseq::MQO_INNER_OBJECT *makePolygon(MQO_MATDATA *M,int n_mat,MQO_OBJDATA *obj,glPOINT3f *N,unsigned char alpha) ; void makeArray(cGLMetaseq::MQO_MATERIAL *mat,int matpos,MQO_OBJDATA *obj,glPOINT3f *N) ; cGLMetaseq::MQO_OBJECT *makeObjects(MQO_MATDATA *M,int n_mat,vector *objs,unsigned char alpha) ; */ void readMaterial(FILE *fp, MQO_MATDATA M[]) { GLfloat dif, amb, emi, spc; GLfloat c[4]; char buf[256]; char *pStrEnd, *pStr; int len; int i = 0; while (1) { fgets(buf,sizeof(buf),fp); // 行読み込み if (strstr(buf,"}")) break; pStr = strstr(buf,"col("); // 材質名読み飛ばし sscanf( pStr, "col(%f %f %f %f) dif (%f) amb(%f) emi(%f) spc(%f) power(%f)", &c[0], &c[1], &c[2], &c[3], &dif, &amb, &emi, &spc, &M[i].power ); // 頂点カラー memcpy(M[i].col,c,sizeof(M[i].col)) ; // 拡散光 M[i].dif[0] = dif * c[0]; M[i].dif[1] = dif * c[1]; M[i].dif[2] = dif * c[2]; M[i].dif[3] = c[3]; // 周囲光 M[i].amb[0] = amb * c[0]; M[i].amb[1] = amb * c[1]; M[i].amb[2] = amb * c[2]; M[i].amb[3] = c[3]; // 自己照明 M[i].emi[0] = emi * c[0]; M[i].emi[1] = emi * c[1]; M[i].emi[2] = emi * c[2]; M[i].emi[3] = c[3]; // 反射光 M[i].spc[0] = spc * c[0]; M[i].spc[1] = spc * c[1]; M[i].spc[2] = spc * c[2]; M[i].spc[3] = c[3]; // tex:模様マッピング名 if ( (pStr = strstr(buf,"tex(")) != NULL ) { M[i].useTex = true; pStrEnd = strstr(pStr,")")-1; len = pStrEnd - (pStr+5); strncpy(M[i].texFile,pStr+5,len); M[i].texFile[len] = (char)0; if ( (pStr = strstr(buf,"aplane(")) != NULL ) { pStrEnd = strstr(pStr,")")-1; len = pStrEnd - (pStr+8); strncpy(M[i].alpFile,pStr+8,len); M[i].alpFile[len] = (char)0; } else { M[i].alpFile[0] = (char)0; } } else { M[i].useTex = false; M[i].texFile[0] = (char)0; M[i].alpFile[0] = (char)0; } i++; } } void readVertex(FILE *fp, glPOINT3f V[],PFNMETASEQTRANSANDSCALEPROC transproc,float scale) { char buf[256]; int i=0; while (1) { fgets(buf,sizeof(buf),fp); if (strstr(buf,"}")) break; sscanf(buf,"%f %f %f",&V[i].x,&V[i].y,&V[i].z); if( transproc != NULL ) transproc(&V[i].x,&V[i].y,&V[i].z) ; if( scale != 1.0 ) { V[i].x *= scale ; V[i].y *= scale ; V[i].z *= scale ; } i++; } } int readBVertex(FILE *fp, glPOINT3f V[],PFNMETASEQTRANSANDSCALEPROC transproc,float scale) { int n_vertex,i; float *wf; int size; char cw[256]; char *pStr; fgets(cw,sizeof(cw),fp); if ( (pStr = strstr(cw,"Vector")) != NULL ) { sscanf(pStr,"Vector %d [%d]",&n_vertex,&size); // 頂点数、データサイズを読み込む } else { return -1; } //MQOファイルのバイナリ頂点データはintel形式(リトルエディアン) wf = (float *)malloc(size); fread(wf,size,1,fp); for ( i = 0; i < n_vertex; i++ ) { V[i].x = wf[i*3+0]; V[i].y = wf[i*3+1]; V[i].z = wf[i*3+2]; #if DEF_IS_LITTLE_ENDIAN #else endianConverter((void *)&V[i].x,sizeof(V[i].x)); endianConverter(&V[i].y,sizeof(V[i].y)); endianConverter(&V[i].z,sizeof(V[i].z)); #endif if( transproc != NULL ) transproc(&V[i].x,&V[i].y,&V[i].z) ; if( scale != 1.0 ) { V[i].x *= scale ; V[i].y *= scale ; V[i].z *= scale ; } } free(wf); // "}"まで読み飛ばし { char buf[256]; while (1) { fgets(buf,sizeof(buf),fp); if (strstr(buf,"}")) break; } } return n_vertex; } void readFace(FILE *fp, MQO_OBJDATA *obj) { char buf[256]; char *pStr; MQO_FACE F[2] ; int fn ; while (1) { fgets(buf,sizeof(buf),fp); if (strstr(buf,"}")) break; // 面を構成する頂点数 sscanf(buf,"%d",&fn); if( fn == 3 ) { // 頂点(V)の読み込み if ( (pStr = strstr(buf,"V(")) != NULL ) { sscanf(pStr,"V(%d %d %d)",&F[0].v[0],&F[0].v[1],&F[0].v[2]); } // マテリアル(M)の読み込み F[0].m = 0; if ( (pStr = strstr(buf,"M(")) != NULL ) { sscanf(pStr,"M(%d)",&F[0].m); } else { // マテリアルが設定されていない面 F[0].m = -1 ; } // UVマップ(UV)の読み込み if ( (pStr = strstr(buf,"UV(")) != NULL ) { sscanf(pStr,"UV(%f %f %f %f %f %f)", &F[0].uv[0].x, &F[0].uv[0].y, &F[0].uv[1].x, &F[0].uv[1].y, &F[0].uv[2].x, &F[0].uv[2].y ); } obj->F.push_back(F[0]) ; } // 頂点配列はすべて三角にするので、四角は三角x2に分割 // 0 3 0 0 3 // □ → △  ▽ // 1 2 1 2 2 // 0 1 0 0 1 // □ → △  ▽ // 3 2 3 2 2 //☆メタセコの頂点は面に対して右回り、OpenGLは左回りがデフォルト //☆描画時にglFrontFaceで切り替える。 if( fn == 4 ) { int dmy; // 頂点(V)の読み込み if ( (pStr = strstr(buf,"V(")) != NULL ) { sscanf(pStr,"V(%d %d %d %d)",&F[0].v[0],&F[0].v[1],&F[0].v[2],&dmy); sscanf(pStr,"V(%d %d %d %d)",&F[1].v[0],&dmy,&F[1].v[1],&F[1].v[2]); } // マテリアル(M)の読み込み F[0].m = 0; if ( (pStr = strstr(buf,"M(")) != NULL ) { sscanf(pStr,"M(%d)",&F[0].m); } else { // マテリアルが設定されていない面 F[0].m = -1 ; } F[1].m = F[0].m ; // UVマップ(UV)の読み込み if ( (pStr = strstr(buf,"UV(")) != NULL ) { sscanf(pStr,"UV(%f %f %f %f %f %f %f %f)", &F[0].uv[0].x, &F[0].uv[0].y, &F[0].uv[1].x, &F[0].uv[1].y, &F[0].uv[2].x, &F[0].uv[2].y, &dmy, &dmy ); sscanf(pStr,"UV(%f %f %f %f %f %f %f %f)", &F[1].uv[0].x, &F[1].uv[0].y, &dmy, &dmy, &F[1].uv[1].x, &F[1].uv[1].y, &F[1].uv[2].x, &F[1].uv[2].y ); } obj->F.push_back(F[0]) ; obj->F.push_back(F[1]) ; } } } void readObject(FILE *fp, MQO_OBJDATA *obj,PFNMETASEQTRANSANDSCALEPROC transproc,float scale) { char buf[256]; while (1) { fgets(buf,sizeof(buf),fp); if (strstr(buf,"}")) break; // visible if (strstr(buf,"visible ")) { sscanf(buf," visible %d", &obj->visible); } // shading if (strstr(buf,"shading ")) { sscanf(buf," shading %d", &obj->shading); } // facet if (strstr(buf,"facet ")) { sscanf(buf," facet %f", &obj->facet); } // vertex if (strstr(buf,"vertex ")) { sscanf(buf," vertex %d", &obj->n_vertex); obj->V = new glPOINT3f[obj->n_vertex] ; memset(obj->V,0,sizeof(glPOINT3f)*obj->n_vertex) ; readVertex(fp, obj->V,transproc,scale); } // BVertex if (strstr(buf,"BVertex")) { sscanf(buf," BVertex %d", &obj->n_vertex); obj->V = new glPOINT3f[obj->n_vertex] ; memset(obj->V,0,sizeof(glPOINT3f)*obj->n_vertex) ; readBVertex(fp,obj->V,transproc,scale); } // face if (strstr(buf,"face ")) { // int n_face ; // sscanf(buf," face %d", &n_face); // obj->F = new MQO_FACE[obj->n_face] ; readFace(fp, obj); } } } cGLMetaseq::MQO_OBJECT * loadFile(char *filename, PFNMETASEQTRANSANDSCALEPROC transproc,float scale) { FILE *fp; MQO_OBJDATA *obj; vector objs ; MQO_MATDATA *M = NULL; cGLMetaseq::MQO_OBJECT *ret ; char buf[256]; // 文字列読み込みバッファ char path_dir[256]; // ディレクトリのパス char path_tex[256]; // テクスチャファイルのパス char path_alp[256]; // アルファテクスチャファイルのパス int n_mat = 0; // マテリアル数 int n_obj = 0; // オブジェクト数 int i; // MaterialとObjectの読み込み fp = fopen(filename,"rb"); if (fp==NULL) return NULL; while ( !feof(fp) ) { fgets(buf,sizeof(buf),fp); // Material if (strstr(buf,"Material")) { sscanf(buf,"Material %d", &n_mat); M = new MQO_MATDATA[n_mat] ; memset(M,0,sizeof(MQO_MATDATA)*n_mat) ; readMaterial(fp,M); } // Object if (strstr(buf,"Object")) { obj = new MQO_OBJDATA ; sscanf(buf,"Object %s", obj->objname); readObject(fp, obj,transproc,scale); objs.push_back(obj) ; } } fclose(fp); n_obj = (int)objs.size() ; // パスの取得 char *pStr; int len; pStr = MAX( strrchr(filename,'\\'), strrchr(filename,'/') ); len = MAX((int)(pStr-filename)+1,0); strncpy(path_dir,filename,len); path_dir[len] = (char)0; // テクスチャの登録 for (i=0; iset(path_tex,path_alp); } else { M[i].texName = m_texPool->set(path_tex,NULL); } } else { M[i].texName = 0 ; } } ret = makeObjects(M,n_mat,&objs) ; printf("%s", filename); // オブジェクトのデータの開放 for (i=0; iV ; obj->F.clear() ; delete obj ; } objs.clear() ; // マテリアルの開放 delete[] M; return ret ; } void snormal(glPOINT3f A, glPOINT3f B, glPOINT3f C, glPOINT3f *normal) { double norm; glPOINT3f vec0,vec1; // ベクトルBA vec0.x = A.x - B.x; vec0.y = A.y - B.y; vec0.z = A.z - B.z; // ベクトルBC vec1.x = C.x - B.x; vec1.y = C.y - B.y; vec1.z = C.z - B.z; // 法線ベクトル normal->x = vec0.y * vec1.z - vec0.z * vec1.y; normal->y = vec0.z * vec1.x - vec0.x * vec1.z; normal->z = vec0.x * vec1.y - vec0.y * vec1.x; // 正規化 norm = normal->x * normal->x + normal->y * normal->y + normal->z * normal->z; norm = sqrt ( norm ); normal->x /= norm; normal->y /= norm; normal->z /= norm; } //戻り値のdelete[]が必要 cGLMetaseqParent::glPOINT3f *vertexNormal(MQO_OBJDATA *obj) { int f; int n_face ; int v; int i; double len; glPOINT3f fnormal; // 面法線ベクトル // vector *F; glPOINT3f *V; glPOINT3f *ret; // F = &obj->F; V = obj->V; ret = new glPOINT3f[obj->n_vertex] ; memset(ret,0,sizeof(glPOINT3f)*obj->n_vertex) ; if( ret == NULL ) return NULL ; n_face = (int)obj->F.size() ; for( f = 0 ; f < n_face ; f++ ) { MQO_FACE &F = obj->F.at(f) ; snormal(V[F.v[0]],V[F.v[1]],V[F.v[2]],&fnormal); for ( i = 0; i < 3; i++ ) { ret[F.v[i]].x += fnormal.x; ret[F.v[i]].y += fnormal.y; ret[F.v[i]].z += fnormal.z; } } //正規化 for ( v = 0; v < obj->n_vertex; v++ ) { if ( ret[v].x == 0 && ret[v].y == 0 && ret[v].z == 0 ) { //面に使われてない点 continue; } len = sqrt(ret[v].x*ret[v].x + ret[v].y*ret[v].y + ret[v].z*ret[v].z); if ( len != 0 ) { ret[v].x = ret[v].x/len; ret[v].y = ret[v].y/len; ret[v].z = ret[v].z/len; } } return ret ; } cGLMetaseq::MQO_INNER_OBJECT * makePolygon(MQO_MATDATA *M,int n_mat,MQO_OBJDATA *obj,glPOINT3f *N) { cGLMetaseq::MQO_INNER_OBJECT *ret ; ret = new cGLMetaseq::MQO_INNER_OBJECT ; strcpy(ret->objname,obj->objname) ; ret->isVisible = (obj->visible != 0) ; ret->isShadingFlat = (obj->shading == 0) ; ret->minPoint[0] = 0 ; ret->minPoint[1] = 0 ; ret->minPoint[2] = 0 ; ret->maxPoint[0] = 0 ; ret->maxPoint[1] = 0 ; ret->maxPoint[2] = 0 ; // faceの中でのマテリアル毎の頂点の数 // M=NULLのとき、F[].m = 0 が入ってくる if ( M == NULL ) n_mat = 1; size_t f,f_num ; int *mat_vnum ; mat_vnum = (int *)malloc(sizeof(int)*n_mat); memset(mat_vnum,0,sizeof(int)*n_mat); f_num = obj->F.size() ; for( f = 0 ; f < f_num ; f++ ) { if( obj->F[f].m < 0 ) continue ; mat_vnum[obj->F[f].m] += 3 ; } int m ; GLfloat defcol[4]; GLfloat *pcol; for( m = 0 ; m < n_mat ; m++ ) { cGLMetaseq::MQO_MATERIAL material ; memset(&material,0,sizeof(material)) ; material.datanum = mat_vnum[m] ; material.isValidMaterialInfo = (M != NULL) ; if( mat_vnum[m] <= 0 ) { continue ; } if( material.isValidMaterialInfo ) { memcpy(material.dif,M[m].dif,sizeof(material.dif)); memcpy(material.amb,M[m].amb,sizeof(material.amb)); memcpy(material.spc,M[m].spc,sizeof(material.spc)); memcpy(material.emi,M[m].emi,sizeof(material.emi)); material.power = M[m].power; material.isUseTexture = M[m].useTex; pcol = M[m].col; } else { defcol[0] = 1.0; defcol[1] = 1.0; defcol[2] = 1.0; defcol[3] = 1.0; material.isUseTexture = 0; pcol = defcol; } memcpy(material.color,pcol,sizeof(material.color)) ; if ( material.isUseTexture ) { material.vertex_t = (cGLMetaseq::VERTEX_TEXUSE *)calloc(material.datanum,sizeof(cGLMetaseq::VERTEX_TEXUSE)); material.texture_id = M[m].texName; } else { material.vertex_p = (cGLMetaseq::VERTEX_NOTEX *)calloc(material.datanum,sizeof(cGLMetaseq::VERTEX_NOTEX)); } makeArray(&material,m,obj,N); if ( material.isUseTexture ) { if( m == 0 ) { ret->minPoint[0] = material.vertex_t[0].point[0]; ret->minPoint[1] = material.vertex_t[0].point[1]; ret->minPoint[2] = material.vertex_t[0].point[2]; ret->maxPoint[0] = material.vertex_t[0].point[0]; ret->maxPoint[1] = material.vertex_t[0].point[1]; ret->maxPoint[2] = material.vertex_t[0].point[2]; } for( int num = 0 ; num < material.datanum ; num++ ) { for( int xyz = 0 ; xyz < 3 ; xyz++ ) { if( material.vertex_t[num].point[xyz] < ret->minPoint[xyz] ) ret->minPoint[xyz] = material.vertex_t[num].point[xyz] ; if( ret->maxPoint[xyz] < material.vertex_t[num].point[xyz] ) ret->maxPoint[xyz] = material.vertex_t[num].point[xyz] ; } } } else { if( m == 0 ) { ret->minPoint[0] = material.vertex_p[0].point[0]; ret->minPoint[1] = material.vertex_p[0].point[1]; ret->minPoint[2] = material.vertex_p[0].point[2]; ret->maxPoint[0] = material.vertex_p[0].point[0]; ret->maxPoint[1] = material.vertex_p[0].point[1]; ret->maxPoint[2] = material.vertex_p[0].point[2]; } for( int num = 0 ; num < material.datanum ; num++ ) { for( int xyz = 0 ; xyz < 3 ; xyz++ ) { if( material.vertex_p[num].point[xyz] < ret->minPoint[xyz] ) ret->minPoint[xyz] = material.vertex_p[num].point[xyz] ; if( ret->maxPoint[xyz] < material.vertex_p[num].point[xyz] ) ret->maxPoint[xyz] = material.vertex_p[num].point[xyz] ; } } } if (m_isVBOSupported) { if ( material.isUseTexture ) { glGenBuffersARB( 1, &material.VBO_id ); glBindBufferARB( GL_ARRAY_BUFFER_ARB, material.VBO_id ); glBufferDataARB( GL_ARRAY_BUFFER_ARB, material.datanum*sizeof(cGLMetaseq::VERTEX_TEXUSE), material.vertex_t, GL_STATIC_DRAW_ARB ); } else { glGenBuffersARB( 1, &material.VBO_id ); glBindBufferARB( GL_ARRAY_BUFFER_ARB, material.VBO_id ); glBufferDataARB( GL_ARRAY_BUFFER_ARB, material.datanum*sizeof(cGLMetaseq::VERTEX_NOTEX), material.vertex_p, GL_STATIC_DRAW_ARB ); } } ret->mat.push_back(material) ; } return ret ; } void makeArray(cGLMetaseq::MQO_MATERIAL *mat,int matpos,MQO_OBJDATA *obj,glPOINT3f *N) { glPOINT3f normal; // 法線ベクトル size_t f,f_num ; f_num = obj->F.size() ; int dpos ; dpos = 0 ; int i ; double s ; glPOINT3f *V; V = obj->V ; if( mat->isUseTexture ) { for( f = 0 ; f < f_num ; f++ ) { MQO_FACE &F = obj->F.at(f) ; if( F.m != matpos ) continue ; snormal(V[F.v[0]],V[F.v[1]],V[F.v[2]],&normal); // 法線ベクトルを計算 for ( i = 0; i < 3; i++ ) { mat->vertex_t[dpos].point[0] = V[F.v[i]].x; mat->vertex_t[dpos].point[1] = V[F.v[i]].y; mat->vertex_t[dpos].point[2] = V[F.v[i]].z; mat->vertex_t[dpos].uv[0] = F.uv[i].x; mat->vertex_t[dpos].uv[1] = F.uv[i].y; s = acos(normal.x*N[F.v[i]].x + normal.y*N[F.v[i]].y + normal.z*N[F.v[i]].z); if ( obj->facet < s ) { // スムージング角 <(頂点法線と面法線の角度)のときは面法線を頂点法線とする mat->vertex_t[dpos].normal[0] = normal.x; mat->vertex_t[dpos].normal[1] = normal.y; mat->vertex_t[dpos].normal[2] = normal.z; } else { mat->vertex_t[dpos].normal[0] = N[F.v[i]].x; mat->vertex_t[dpos].normal[1] = N[F.v[i]].y; mat->vertex_t[dpos].normal[2] = N[F.v[i]].z; } dpos++; } } } else { for ( f = 0; f < f_num; f++ ){ MQO_FACE &F = obj->F.at(f) ; if ( F.m != matpos ) continue; snormal(V[F.v[0]],V[F.v[1]],V[F.v[2]],&normal); // 法線ベクトルを計算 for ( i = 0; i < 3; i++ ) { mat->vertex_p[dpos].point[0] = V[F.v[i]].x; mat->vertex_p[dpos].point[1] = V[F.v[i]].y; mat->vertex_p[dpos].point[2] = V[F.v[i]].z; mat->vertex_p[dpos].normal[0] = normal.x; mat->vertex_p[dpos].normal[1] = normal.y; mat->vertex_p[dpos].normal[2] = normal.z; s = acos(normal.x*N[F.v[i]].x + normal.y*N[F.v[i]].y + normal.z*N[F.v[i]].z); if ( obj->facet < s ) { mat->vertex_p[dpos].normal[0] = normal.x; mat->vertex_p[dpos].normal[1] = normal.y; mat->vertex_p[dpos].normal[2] = normal.z; } else { mat->vertex_p[dpos].normal[0] = N[F.v[i]].x; mat->vertex_p[dpos].normal[1] = N[F.v[i]].y; mat->vertex_p[dpos].normal[2] = N[F.v[i]].z; } dpos++; } } } } cGLMetaseq::MQO_OBJECT * makeObjects(MQO_MATDATA *M,int n_mat,vector *objs) { cGLMetaseq::MQO_OBJECT *ret ; ret = new cGLMetaseq::MQO_OBJECT ; if( ret == NULL ) return NULL ; glPOINT3f *N ; cGLMetaseq::MQO_INNER_OBJECT * inner ; MQO_OBJDATA * obj ; size_t max ; size_t o ; max = objs->size() ; for( o = 0 ; o < max ; o++ ) { obj = objs->at(o) ; N = vertexNormal(obj) ; if( N == NULL ) continue; inner = makePolygon(M,n_mat,obj,N) ; if( inner != NULL ) { if( o == 0 ) { ret->minPoint[0] = inner->minPoint[0] ; ret->minPoint[1] = inner->minPoint[1] ; ret->minPoint[2] = inner->minPoint[2] ; ret->maxPoint[0] = inner->maxPoint[0] ; ret->maxPoint[1] = inner->maxPoint[1] ; ret->maxPoint[2] = inner->maxPoint[2] ; } else { for( int xyz = 0 ; xyz < 3 ; xyz++ ) { if( inner->minPoint[xyz] < ret->minPoint[0] ) ret->minPoint[xyz] = inner->minPoint[xyz] ; if( ret->maxPoint[xyz] < inner->maxPoint[xyz] ) ret->maxPoint[xyz] = inner->maxPoint[xyz] ; } } ret->obj.push_back(inner) ; } delete[] N ; } return ret ; } } ; #endif