前回も説明した関数を少し説明しておきます。
MP3のオープンと開いたファイルにエイリアスをつけておきます。
mciSendString(TEXT("open ../Release/zzz.mp3 alias __MP3__"), NULL, 0, NULL);
音声にオフセットをつけます。微妙なタイミングの調整ですね。
mciSendString(TEXT("seek __MP3__ to 400"), NULL, 0, 0);
音声を再生します。
mciSendString(TEXT("play __MP3__ notify"), NULL, 0, hWnd);
再生中の音声の位置を取得します。下記ソースではそこから更新タイミングを算出しています。
mciSendString(TEXT("status __MP3__ position"), szBuf, sizeof(szBuf) / sizeof(TCHAR), NULL);
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") #ifdef _DEBUG #pragma comment(lib,"../../freeglut-2.8.1/lib/x86/Debug/freeglut.lib") #pragma comment(lib,"../../glew-1.11.0/lib/Debug/Win32/glew32d.lib") #pragma comment(lib,"../../bullet3-master/bin/BulletCollision_vs2010_debug.lib") #pragma comment(lib,"../../bullet3-master/bin/BulletDynamics_vs2010_debug.lib") #pragma comment(lib,"../../bullet3-master/bin/LinearMath_vs2010_debug.lib") #else #pragma comment(lib,"../../freeglut-2.8.1/lib/x86/freeglut.lib") #pragma comment(lib,"../../glew-1.11.0/lib/Release/Win32/glew32.lib") #pragma comment(lib,"../../bullet3-master/bin/BulletCollision_vs2010.lib") #pragma comment(lib,"../../bullet3-master/bin/BulletDynamics_vs2010.lib") #pragma comment(lib,"../../bullet3-master/bin/LinearMath_vs2010.lib") #endif #ifdef _WIN32 #include <windows.h> #include <Mmsystem.h> #endif #include <stdio.h> #include <string.h> #include <GL/glut.h> #include "../BulletPhysics/BulletPhysics.h" #include "../MMD/PMDModel.h" #include "../MMD/VMDMotion.h" extern cBulletPhysics g_clBulletPhysics; static cPMDModel g_clPMDModel; static cVMDMotion g_clVMDMotion; static Matrix g_matPlanarProjection; static int Frames; static int Mp3prevtime = 0; //---------------------------------------------------- void Initialize(void) { glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClearStencil( 0 ); // ステンシル用。 glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_TEXTURE_2D); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); const float fLightPos[] = { 0.45f, 0.55f, 1.0f, 0.0f }; const float fLightDif[] = { 0.9f, 0.9f, 0.9f, 1.0f }; const float fLightAmb[] = { 0.9f, 0.9f, 0.9f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, fLightPos); glLightfv(GL_LIGHT0, GL_DIFFUSE, fLightDif); glLightfv(GL_LIGHT0, GL_AMBIENT, fLightAmb); glLightfv(GL_LIGHT0, GL_SPECULAR, fLightAmb); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); { // ステンシル用 Vector4 vec4Plane = { 0.0f, 1.0f, 0.0f, 0.0f }; Vector3 vec4LightPos = { 10.0f, 70.0f, -20.0f }; MatrixPlanarProjection( g_matPlanarProjection, &vec4Plane, &vec4LightPos ); } g_clBulletPhysics.initialize(); mciSendString(TEXT("open ../Release/zzz.mp3 alias __MP3__"), NULL, 0, NULL); mciSendString(TEXT("seek __MP3__ to 400"), NULL, 0, 0); SetCurrentDirectory("../models/xxx/"); // ファイルをアクセスためのパスを設定。Release/***.exeから考える。 g_clPMDModel.load("xxx.pmd"); // PMDファイルを登録 g_clVMDMotion.load("../motion/xxx.vmd"); // VMDファイルを登録 g_clPMDModel.setMotion(&g_clVMDMotion, false); // モデルをモーションに紐付け g_clPMDModel.updateMotion(0.0f); // プレイ時間を初期化 g_clPMDModel.resetRigidBodyPos(); // モデルを初期化 Frames = 0; glClearColor(0.0, 1.0, 1.0, 1.0); //背景色 } //---------------------------------------------------- static float lscalef = 1.0f; void Display(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( /* field of view in degree */ 40.0,/* aspect ratio */ 1.0,/* Z near */ 1.0, /* Z far */ 500.0); gluLookAt(0, 20, 50, /* eye is at (0,0,5) */ 0.0, 10.0, 0.0, /* center is at (0,0,0) */ 0.0, 1.0, 0.); /* up is in positive Y direction */ glEnable( GL_LIGHTING ); glDepthFunc(GL_LEQUAL); glEnable(GL_NORMALIZE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); glScalef(1.0f*lscalef, 1.0f*lscalef, -1.0f*lscalef); g_clPMDModel.render(); { // ステンシル用 glDisable( GL_CULL_FACE ); glDisable( GL_TEXTURE_2D ); glDisable( GL_LIGHTING ); glEnable( GL_STENCIL_TEST ); // ステンシルバッファに書き込むよ。 glStencilFunc( GL_ALWAYS, 1, ~0 ); glStencilOp( GL_REPLACE, GL_KEEP, GL_REPLACE ); glColorMask( 0, 0, 0, 0 ); // カラーバッファに書き込むのを禁止 glDepthMask(GL_FALSE); // デプスバッファに書き込むのを禁止 glMultMatrixf( (const float *)g_matPlanarProjection ); // 光源から見たようにキャンバスを設定。 g_clPMDModel.renderForShadow(); // ここから通常描画に戻る。 glColorMask( 1, 1, 1, 1 ); // カラーに書き込み許可 glDepthMask(GL_TRUE); // デプスに書き込む許可 float fWndW = glutGet( GLUT_WINDOW_WIDTH ), fWndH = glutGet( GLUT_WINDOW_HEIGHT ); glStencilFunc( GL_EQUAL, 1, ~0); // デフォルトに戻す。 glStencilOp( GL_KEEP, GL_KEEP ,GL_KEEP ); // ステンシルには書かない! // 正面から見たテクスチャを1枚貼る glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0.0f, fWndW, 0.0f, fWndH ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glColor4f( 1.0f, 0.2f, 0.2f, 0.5f ); glBegin( GL_TRIANGLE_FAN ); glVertex2f( 0.0f, fWndH ); glVertex2f( fWndW, fWndH ); glVertex2f( fWndW, 0.0f ); glVertex2f( 0.0f, 0.0f ); glEnd(); glDisable( GL_STENCIL_TEST ); } glPopMatrix(); } glutSwapBuffers(); // ダブルバッファリング } //---------------------------------------------------- float getSoundFrame(void) { float frame_ms = 30.0f; char szBuf[256]; int dwMsec; float fDiffTime; mciSendString(TEXT("status __MP3__ position"), szBuf, sizeof(szBuf) / sizeof(TCHAR), NULL); dwMsec = strtoul(szBuf, NULL, 0); fDiffTime = (float)(dwMsec - Mp3prevtime) * (frame_ms / 1000.0f); Mp3prevtime = dwMsec; return fDiffTime; } void Idle(void) { Vector3 vecCamPos; if (Frames == 0){ HDC glDc = wglGetCurrentDC(); HWND hWnd = WindowFromDC(glDc); mciSendString(TEXT("play __MP3__ notify"), NULL, 0, hWnd); } float fElapsedFrame = getSoundFrame(); // getElapsedFrame(); if (fElapsedFrame > 10.0f) fElapsedFrame = 10.0f; g_clPMDModel.updateMotion(fElapsedFrame); g_clPMDModel.updateNeckBone(&vecCamPos); g_clBulletPhysics.update(fElapsedFrame); g_clPMDModel.updateSkinning(); Frames++; glutPostRedisplay(); } //---------------------------------------- void Visibility(int visible) { if (visible == GLUT_VISIBLE) glutIdleFunc(Idle); else glutIdleFunc(NULL); } //---------------------------------------------------- void Cleanup(void) { g_clPMDModel.release(); // PMD,VMDが取得したメモリを解放 g_clBulletPhysics.release(); // Bulletが取得したメモリを解放 } //---------------------------------------------------- int main(int argc, char *argv[]) { glutInit(&argc, argv); // glut の初期化 glutInitWindowPosition( 100 , 100 ); // ウィンドウの位置 glutInitWindowSize( 640, 480 ); // ウィンドウサイズ glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL ); // ディスプレイモード glutCreateWindow("MMDapr1"); // ウィンドウ作成 glutDisplayFunc(Display); // 描画時コールバック glutVisibilityFunc(Visibility); glutIdleFunc(Idle); // アイドル時コールバック atexit(Cleanup); // 終了時コールバック(メモリ解放など Initialize(); // 初期設定 glutMainLoop(); return 0; }
0 件のコメント:
コメントを投稿