前回も説明した関数を少し説明しておきます。
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 件のコメント:
コメントを投稿