0001: // ---------------------------------------------------------------------------
0002: // tms.cpp
0003: //      T-pot engine MeSh format
0004: // ---------------------------------------------------------------------------
0005: 
0006: #include <windows.h>                                            // Header File For Windows
0007: #include <GL/glut.h>
0008: #include "te_tms.h"
0009: 
0010: #define DISPLAY_LIST// ディスプレイリストを使って表示
0011: #define NO_VBOS     // VBO の強制OFF
0012: 
0013: namespace Te
0014: {
0015: // glext.h からの VBO Extension の定義
0016: #define GL_ARRAY_BUFFER_ARB 0x8892
0017: #define GL_STATIC_DRAW_ARB 0x88E4
0018: typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC)    (GLenum target, GLuint buffer);
0019: typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
0020: typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC)    (GLsizei n, GLuint *buffers);
0021: typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC)    (GLenum target, int size, const GLvoid *data, GLenum usage);
0022: 
0023: // VBO Extension 関数のポインタ
0024: PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;                  // VBO 名前生成
0025: PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;                  // VBO 結びつけ
0026: PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;                  // VBO データロード
0027: PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;            // VBO 削除
0028: 
0029: bool CTms::_fVBOSupported = FALSE;
0030: 
0031: // ===========================================================================
0032: // 公開関数
0033: // ===========================================================================
0034: 
0035: 
0036: // ---------------------------------------------------------------------------
0037: // TMS の初期化
0038: // ---------------------------------------------------------------------------
0039: PTMS SetupTms( const PTMS_DATA data )
0040: {
0041:     CTms *pTms = new CTms( data );
0042:     
0043:     return (PTMS)pTms;
0044: }
0045: 
0046: // ---------------------------------------------------------------------------
0047: // TMS の片付け
0048: // ---------------------------------------------------------------------------
0049: void ClenaTms( PTMS p )
0050: {
0051:     CTms *pTms = (CTms *)p;
0052:     
0053:     delete pTms;
0054: }
0055: 
0056: // ---------------------------------------------------------------------------
0057: // TMS の描画
0058: // ---------------------------------------------------------------------------
0059: void RenderTms( PTMS p )
0060: {
0061:     CTms *pTms = (CTms *)p;
0062:     
0063:     pTms->Render();
0064: }
0065: 
0066: 
0067: // ===========================================================================
0068: // メッシュクラス
0069: // ===========================================================================
0070: 
0071: // ---------------------------------------------------------------------------
0072: // システムの初期化
0073: // ---------------------------------------------------------------------------
0074: void CTms::Initialize()
0075: {
0076:     CheckDeviceAbility();
0077: }
0078: 
0079: 
0080: // ---------------------------------------------------------------------------
0081: // コンストラクタ
0082: // ---------------------------------------------------------------------------
0083: CTms::CTms( const PTMS_DATA p )
0084: {
0085:     const PTMS_HEADER pHeader = (const PTMS_HEADER)p;
0086:     _nVertex = pHeader->vertex_count;
0087:     
0088:     // -----------------------------------------------------------------------
0089:     // データ配列の所得
0090:     // -----------------------------------------------------------------------
0091:     _pPosition = (const float *)(pHeader+1);
0092:     _pNormal   = _pPosition + 3 * _nVertex;
0093:     _pTexCoord = _pNormal   + 3 * _nVertex;
0094: 
0095: #ifdef DISPLAY_LIST
0096:     _iDisplayList = glGenLists(1);
0097:     glNewList( _iDisplayList, GL_COMPILE );
0098: 
0099:         glBegin( GL_TRIANGLES );
0100:         // ディスプレイリストの作成
0101:         for( unsigned int i = 0; i < _nVertex; i++ )
0102:         {
0103:             glNormal3fv  (   _pNormal ); _pNormal   += 3;
0104:             glTexCoord2fv( _pTexCoord ); _pTexCoord += 2;
0105:             glVertex3fv  ( _pPosition ); _pPosition += 3;
0106:         }
0107:         glEnd();
0108: 
0109:     glEndList();
0110: #else
0111: #ifndef NO_VBOS
0112:     // -----------------------------------------------------------------------
0113:     // 頂点データをグラフィックスカードのメモリに格納する。
0114:     // -----------------------------------------------------------------------
0115:     // 位置座標バッファを生成して結びつける
0116:     glGenBuffersARB( 1, &_nVBOPosition );                           // ID を得る
0117:     glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBOPosition );          // バッファを結びつける
0118:     glBufferDataARB( GL_ARRAY_BUFFER_ARB, _nVertex*3*sizeof(float), _pPosition, GL_STATIC_DRAW_ARB );
0119: 
0120:     // 法線ベクトルバッファを生成して結びつける
0121:     glGenBuffersARB( 1, &_nVBONormal );                             // ID を得る
0122:     glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBONormal );            // バッファを結びつける
0123:     glBufferDataARB( GL_ARRAY_BUFFER_ARB, _nVertex*3*sizeof(float), _pNormal, GL_STATIC_DRAW_ARB );
0124: 
0125:     // テクスチャ座標バッファを生成して結びつける
0126:     // Generate And Bind The Texture Coordinate Buffer
0127:     glGenBuffersARB( 1, &_nVBOTexCoord );                           // ID を得る
0128:     glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBOTexCoord );          // バッファを結びつける
0129:     glBufferDataARB( GL_ARRAY_BUFFER_ARB, _nVertex*2*sizeof(float), _pTexCoord, GL_STATIC_DRAW_ARB );
0130: #endif // !NO_VBOS
0131: #endif // DISPLAY_LIST
0132: }
0133: 
0134: 
0135: // ---------------------------------------------------------------------------
0136: // デストラクタ
0137: // ---------------------------------------------------------------------------
0138: CTms::~CTms( )
0139: {
0140: #ifdef DISPLAY_LIST
0141:     glDeleteLists( _iDisplayList, 1 );
0142: #endif // DISPLAY_LIST
0143: 
0144:     // VBO の削除
0145:     if( _fVBOSupported )
0146:     {
0147:         unsigned int nBuffers[] = { _nVBOPosition, _nVBONormal, _nVBOTexCoord };
0148:         glDeleteBuffersARB( 3, nBuffers );
0149:     }
0150: 
0151:     _pTexCoord = 0;
0152:     _pNormal = 0;
0153:     _pPosition = 0;
0154:     _nVertex = 0;
0155: }
0156: 
0157: // ---------------------------------------------------------------------------
0158: // エクステンションのサポートを調べる
0159: // ---------------------------------------------------------------------------
0160: static bool IsExtensionSupported( char* szTargetExtension )
0161: {
0162:     const unsigned char *pszExtensions = NULL;
0163:     const unsigned char *pszStart;
0164:     unsigned char *pszWhere, *pszTerminator;
0165: 
0166:     // Extension names should not have spaces
0167:     pszWhere = (unsigned char *) strchr( szTargetExtension, ' ' );
0168:     if( pszWhere || *szTargetExtension == '\0' )
0169:         return false;
0170: 
0171:     // Get Extensions String
0172:     pszExtensions = glGetString( GL_EXTENSIONS );
0173: 
0174:     // Search The Extensions String For An Exact Copy
0175:     pszStart = pszExtensions;
0176:     for(;;)
0177:     {
0178:         pszWhere = (unsigned char *) strstr( (const char *) pszStart, szTargetExtension );
0179:         if( !pszWhere )
0180:             break;
0181:         pszTerminator = pszWhere + strlen( szTargetExtension );
0182:         if( pszWhere == pszStart || *( pszWhere - 1 ) == ' ' )
0183:             if( *pszTerminator == ' ' || *pszTerminator == '\0' )
0184:                 return true;
0185:         pszStart = pszTerminator;
0186:     }
0187:     return false;
0188: }
0189: 
0190: // ---------------------------------------------------------------------------
0191: // 描画能力を検証する
0192: // ---------------------------------------------------------------------------
0193: void CTms::CheckDeviceAbility()
0194: {
0195: #ifdef DISPLAY_LIST
0196:     _fVBOSupported = false;
0197:     return;
0198: #endif// DISPLAY_LIST
0199: 
0200:     // VBO のサポートを確認する
0201: #ifndef NO_VBOS
0202:     _fVBOSupported = IsExtensionSupported( "GL_ARB_vertex_buffer_object" );
0203:     if( _fVBOSupported )
0204:     {
0205:         // GL 関数のポインタを所得する
0206:         glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) wglGetProcAddress("glGenBuffersARB");
0207:         glBindBufferARB = (PFNGLBINDBUFFERARBPROC) wglGetProcAddress("glBindBufferARB");
0208:         glBufferDataARB = (PFNGLBUFFERDATAARBPROC) wglGetProcAddress("glBufferDataARB");
0209:         glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffersARB");
0210:     }
0211: #else /* NO_VBOS */
0212:     _fVBOSupported = false;
0213: #endif
0214: }
0215: 
0216: // ---------------------------------------------------------------------------
0217: // 描画
0218: // ---------------------------------------------------------------------------
0219: void CTms::Render( )
0220: {
0221: #ifdef DISPLAY_LIST
0222:     glCallList( _iDisplayList );
0223: #else // DISPLAY_LIST
0224:     // データ配列を有効にする
0225:     glEnableClientState( GL_VERTEX_ARRAY );
0226:     glEnableClientState( GL_NORMAL_ARRAY );
0227:     glEnableClientState( GL_TEXTURE_COORD_ARRAY );
0228: 
0229:     // データをポインタにセットする
0230:     if( _fVBOSupported )
0231:     {
0232:         glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBOPosition );
0233:         glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );
0234:         glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBONormal );
0235:         glNormalPointer( GL_FLOAT, 0, (char *) NULL );
0236:         glBindBufferARB( GL_ARRAY_BUFFER_ARB, _nVBOTexCoord );
0237:         glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL );
0238:     } else
0239:     {
0240:         glVertexPointer( 3, GL_FLOAT, 0, _pPosition );
0241:         glNormalPointer( GL_FLOAT, 0, _pNormal );
0242:         glTexCoordPointer( 2, GL_FLOAT, 0, _pTexCoord );
0243:     }
0244:     
0245:     // 描画
0246:     glDrawArrays( GL_TRIANGLES, 0, _nVertex );
0247: 
0248:     // データ配列を無効にする
0249:     glDisableClientState( GL_VERTEX_ARRAY );
0250:     glDisableClientState( GL_NORMAL_ARRAY );
0251:     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
0252: #endif // DISPLAY_LIST
0253: }
0254: 
0255: }// namespace Te
0256: