初めて
AR
の動作画面を見た時は、とても驚いたことを覚えている。実際にはそこには存在 しないが、カメラを通すと物体があったり、キャラクターがいたり、とても面白そうに感じ た。プログラムを作り始めると、苦労をする部分も多々あったり、理解をするのが難しい部 分もあったが、徐々に自分の作りたいものに近付いているのが実行画面で確認できたので、楽しみながら制作することができた。
また、もう尐し付け加えたかったのが、キーボードの入力の操作である。
Esc
キーを押すと ウィンドウが閉じる、という処理は入れた。その他に、例えばSpace
キーを押せばカボチャ が違うアニメーションをしたり、カボチャが他のキャラクターに変わったりするような処理 もプログラムを作り始めた当初は考えていた。しかし、時間の都合上、これは追加しないこ とにした。本作品を作ることによって、プログラミングの大変さや楽しさを体感することができた。
また、私の数ある夢のひとつ「自分の作ったキャラクターを
3DCG
化し、アニメーションを 作る」ということを実現することができたので満足している。また機会があれば、こういう プログラムを作ってみたい。49
参考文献
*AR入門 身近になった拡張現実
著者:佐野 彰 発行所:株式会社工学社
*ARToolKit 拡張現実感プログラミング入門
著者:橋本 直 発行所:株式会社アスキーメディアワークス
*拡張現実感を実現する
ARToolKit
プログラミングテクニック 著者:谷尻 豊寿 発行所:株式会社カットシステム*14歳からはじめる
C
言語オンラインゲームプログラミング教室 著者:大槻 有一郎 発行所:株式会社ラトルズ*Windowsゲームプログラミング 第
2
版著者:赤坂 玲音 発行所:ソフトバンク クリエイティブ株式会社
*Illustrator リアルイラスト制作テクニック
著者:増井 浩司 発行所:株式会社技術評論社
*メタセコイアからはじめよう!
著者:原田 大輔 発行所:株式会社技術評論社
*Metasequoiaではじめる
3D-CG
モデリング ~高機能フリー3DCGをマスターしよう~著者:鴨杜 健児 発行所:株式会社工学社
*【Illustratorで学ぶ】トレース習熟ドリル
著者:大和宣明 発行所:有限会社ラピュータ
50
謝辞
今回の卒業研究および卒業論文の作成にあたり、終始丁寧で熱心なご指導とご教示を賜り ました高知工科大学工学部電子・光システム工学科綿森 道夫准教授に、学生生活面で特に支 えてくださいました矢野 政顕教授に心から感謝を申し上げます。
また、高知工科大学工学部電子・光システム工学科在学中に本研究実験遂行や学生生活面、
その他各過程で終始ご厚意頂きました、高知工科大学電子・光システム工学科長 岩下 克 教授、木村 正廣教授、神戸 宏教授、河東田 隆教授、真田 克教授、橘 昌良教授、成 沢 忠教授、八田 章光教授、野中 弘二教授、星野 孝総准教授、山本 真行准教授、植 田 和憲講師、高崎 敬雄教育講師、杉田 彰久教育講師、安岡 文子秘書、中山 愛秘書 の皆様には重ねて感謝の意を述べさせていただきます。
51
付録
プログラムリスト
52
ARToolKit を用いたプログラム
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "simple.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <AR/ar.h>
#include <AR/param.h>
#include <AR/video.h>
#include <AR/gsub.h>
#include "GLMetaseq.h"
//パターン
#define OBJ_NUM 2
#define MARK1_ID 1
#define MARK2_ID 2
#define PATT1_NAME "Data/patt.ichi" //マーカー
#define PATT2_NAME "Data/patt.ni" //マーカー
#define OBJ1_SIZE 66.0 //パターンサイズ(単位:mm)
#define OBJ2_SIZE 66.0 //パターンサイズ(単位:mm)
typedef struct{
char *patt_name; //パターン名
int patt_id; //パターンID
int mark_id; //マーカーID
int visible; //検出フラグ
double width; //パターンサイズ(単位:mm)
double center[2]; //パターンの中心座標
double trans[3][4]; //座標変換行列
} OBJECT_T;
53 OBJECT_T object[OBJ_NUM] = {
{ PATT1_NAME, -1, MARK1_ID, 0, OBJ1_SIZE, {0.0, 0.0} }, { PATT2_NAME, -1, MARK2_ID, 0, OBJ2_SIZE, {0.0, 0.0} } };
char *vconf_name = "Data/WDM_camera_flipV.xml"; //ビデオデバイスの設定ファイル char *cparam_name = "Data/camera_para.dat"; //カメラパラメータファイル char *mqo_box = "Data/box2.mqo"; //MQOファイル
char *seq_name = "Sequence/walk_%d.mqo"; //歩くMQO int thresh = 100;
MQO_SEQUENCE mqo_seq; //シーケンス
int n_frame = 42; //フレーム数
MQO_MODEL box; //透明の箱
//3次元オブジェクトの移動量 GLfloat exTx = 0.0;
GLfloat exTy = 0.0;
GLfloat exTz = 0.0;
GLfloat exTx2 = 0.0;
GLfloat exTy2 = 0.0;
GLfloat exTz2 = 0.0;
double depth = -150;
double angle = 0.0;
double angle2 = 0.0; //向き
int dFlag = -1; //深さフラグ
int vFlag = -1;
int Flag = 0;
int aFlag = 0;
double wmat1[3][4], wmat2[3][4]; //変換行列 double wmat3[3][4], wmat4[3][4]; //変換行列 double scaling = 1.0;
int xsize, ysize; //画像サイズ
bool snd1_first = 1;
bool snd2_first;
54 bool snd3_first;
bool snd4_first;
GLubyte *image1; // ビットマップ画像が入る配列 int img1_width, img1_height;
char *bmpfile1 = "Data/idou.bmp";
GLubyte *image2; // ビットマップ画像が入る配列 int img2_width, img2_height;
char *bmpfile2 = "Data/sagasu.bmp";
GLubyte *image3; // ビットマップ画像が入る配列 int img3_width, img3_height;
char *bmpfile3 = "Data/shutsugen.bmp";
GLubyte *image4; // ビットマップ画像が入る配列 int img4_width, img4_height;
char *bmpfile4 = "Data/kieru.bmp";
//プロトタイプ宣言
static void MainLoop(void);
static void DrawObject(double patt_trans[3][4], int markV );
static void MouseEvent(int button, int state, int x, int y);
static void KeyEvent(unsigned char key, int x, int y);
static void Cleanup(void);
static void mySetLight(void);
BOOL CALLBACK dlgProc( HWND, UINT, WPARAM, LPARAM );
void Bitmapread(GLubyte **img_ptr, int* width_ptr, int* height_ptr, char *filename);
int main(int argc, char **argv) {
ARParam cparam; //カメラパラメータ
ARParam wparam; //カメラパラメータ(作業用変数)
int i; //カウンタ
//GLUTの初期化
glutInit(&argc, argv);
55 //ビデオデバイスの設定
if( arVideoOpen( vconf_name ) < 0 ){
printf("ビデオデバイスのエラー");
return -1;
}
//カメラパラメータの設定
if( arVideoInqSize( &xsize, &ysize ) < 0 ){
printf("画像サイズを取得できませんでした\n");
return -1;
}
if( arParamLoad( cparam_name, 1, &wparam ) < 0 ){
printf("カメラパラメータの読み込みに失敗しました\n");
return -1;
}
arParamChangeSize( &wparam, xsize, ysize, &cparam );
arInitCparam( &cparam );
//パターンファイルのロード for( i=0; i < OBJ_NUM; i++ ){
if( ( object[i].patt_id = arLoadPatt(object[i].patt_name) ) < 0 ){
printf("パターンファイルの読み込みに失敗しました\n");
return -1;
} }
//ビットマップ画像の読み込み
Bitmapread(&image1, &img1_width, &img1_height, bmpfile1);
if ( img1_width == 0 || img1_height == 0 ) {
printf("表示文字データの読み込みに失敗しました\n");
return -1;
}
//ビットマップ画像の読み込み
Bitmapread(&image2, &img2_width, &img2_height, bmpfile2);
if ( img2_width == 0 || img2_height == 0 ) {
printf("表示文字データの読み込みに失敗しました\n");
56 return -1;
}
//ビットマップ画像の読み込み
Bitmapread(&image3, &img3_width, &img3_height, bmpfile3);
if ( img3_width == 0 || img3_height == 0 ) {
printf("表示文字データの読み込みに失敗しました\n");
return -1;
}
//ビットマップ画像の読み込み
Bitmapread(&image4, &img4_width, &img4_height, bmpfile4);
if ( img4_width == 0 || img4_height == 0 ) {
printf("表示文字データの読み込みに失敗しました\n");
return -1;
}
//表示倍率のダイアログボックス
HINSTANCE hi = ( HINSTANCE )GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE );
DialogBox( hi, "DIALOG1", HWND_DESKTOP, ( DLGPROC ) dlgProc );
//ウィンドウの設定
argInit( &cparam, scaling, 0, 0, 0, 0 );
//GLMetaseqの初期化 mqoInit();
//シーケンスの読み込み
printf("シーケンスの読み込み中...");
mqo_seq = mqoCreateSequence( seq_name, n_frame, 0.03 );
if( mqo_seq.n_frame <= 0 ){
printf("シーケンスの読み込みに失敗しました\n");
return -1;
}
printf("完了\n");
57 //透明の箱の読み込み
if( ( box = mqoCreateModel( mqo_box, 0.25 ) ) == NULL ){
printf("透明の箱の読み込みに失敗しました\n");
return -1;
}
//ビデオキャプチャの開始 arVideoCapStart();
//メインループの開始
argMainLoop( MouseEvent, KeyEvent, MainLoop );
return 0;
}
void MainLoop(void) {
ARUint8 *image; //カメラ画像
ARMarkerInfo *marker_info; //マーカー検出用の情報
int marker_num; //マーカーらしく部分の個数
int j, k, i;
//カメラ画像の取得
if( ( image = arVideoGetImage() ) == NULL ){
arUtilSleep(2);
return;
}
//カメラ画像の描画 argDrawMode2D();
argDispImage( image, 0, 0 );
//ビットマップ画像の表示 if( dFlag == 1 ){
glRasterPos2i( (int)(scaling * xsize/12), (int)(scaling * ysize/15) );
glPixelZoom( scaling, scaling );
glDrawPixels(img1_width, img1_height, GL_RGB, GL_UNSIGNED_BYTE, image1);
}
58 if( dFlag == 0 ){
//ビットマップ画像の表示 if( aFlag == 1 ){
glRasterPos2i( (int)(scaling * xsize/12), (int)(scaling * ysize/15) );
glPixelZoom( scaling, scaling );
glDrawPixels(img2_width, img2_height, GL_RGB, GL_UNSIGNED_BYTE, image2);
}else{
//ビットマップ画像の表示
glRasterPos2i( (int)(scaling * xsize/12), (int)(scaling * ysize/15) );
glPixelZoom( scaling, scaling );
glDrawPixels(img3_width, img3_height, GL_RGB, GL_UNSIGNED_BYTE, image3);
} }
//ビットマップ画像の表示 if( dFlag == 2 ){
glRasterPos2i( (int)(scaling * xsize/12), (int)(scaling * ysize/15) );
glPixelZoom( scaling, scaling );
glDrawPixels(img4_width, img4_height, GL_RGB, GL_UNSIGNED_BYTE, image4);
}
//マーカの検出と認識
if( arDetectMarker( image, thresh, &marker_info, &marker_num ) < 0 ){
Cleanup();
exit(0);
}
//次の画像のキャプチャ指示 arVideoCapNext();
//3Dオブジェクトを描画するための準備 argDrawMode3D();
argDraw3dCamera( 0, 0 );
//マーカの信頼度の比較
for( i = 0; i < OBJ_NUM; i++ ){
k = -1;
59 for( j = 0; j < marker_num; j++){
if( object[i].patt_id == marker_info[j].id ){
if( k == -1 ) k = j;
else if ( marker_info[k].cf < marker_info[j].cf ) k = j;
} }
//マーカーが見つからなかったとき if( k == -1 ){
object[i].visible = 0;
}
//座標変換行列を取得 else{
arGetTransMat( &marker_info[k], object[i].center, object[i].width, object[i].trans );
object[i].visible = 1;
} }
//マーカーをつとも検出したとき
if( object[0].visible > 0 && object[1].visible > 0 ){
//マーカーの座標系でカメラの位置を取得 arUtilMatInv( object[0].trans, wmat1 );
//マーカーから見たマーカーの位置を取得
arUtilMatMul( wmat1, object[1].trans, wmat2 );
//マーカーへの方向を取得
angle2 = atan2(wmat2[1][3], wmat2[0][3]) * 180 / 3.14 + 90.0;
//マーカーの座標系でカメラの位置を取得 arUtilMatInv( object[1].trans, wmat3 );
//マーカーから見たマーカーの位置を取得
arUtilMatMul( wmat3, object[0].trans, wmat4 );
vFlag = 0;
//音再生
if ( dFlag == 0 ) {
if( !snd3_first ){
60
PlaySound( NULL, NULL, SND_PURGE );
snd3_first = 1;
}
if( snd1_first ){
PlaySound( TEXT("Data/A1_02033.wav"), NULL, SND_ASYNC | SND_FILENAME );
snd1_first = 0;
snd4_first = 1;
}
if( depth >= 0 ){
if( snd4_first ){
PlaySound( TEXT("Data/A1_09176.wav"), NULL, SND_ASYNC | SND_FILENAME | SND_LOOP );
snd4_first = 0;
} }
}
if( dFlag == 1 ){
if( !snd1_first ){
PlaySound( NULL, NULL, SND_PURGE );
snd1_first = 1;
snd2_first = 1;
}
if( snd2_first ){
PlaySound( TEXT("Data/A1_05107.wav"), NULL, SND_ASYNC | SND_FILENAME | SND_LOOP );
snd2_first = 0;
} }
if( dFlag == 2 ){
if( !snd2_first ){
PlaySound( NULL, NULL, SND_PURGE );
snd2_first = 1;
snd3_first = 1;
}
if( snd3_first ){
PlaySound( TEXT("Data/A1_02034.wav"), NULL, SND_ASYNC | SND_FILENAME );
61 snd3_first = 0;
} }
if( Flag == 0 ){
dFlag = 0;
Flag = 1;
}
DrawObject( object[0].trans, vFlag );
}
else if( object[0].visible == 1 ){ //マーカーだけ検出
vFlag = 1;
DrawObject( object[0].trans, vFlag );
}
else if( object[1].visible == 1 ){ //マーカーだけ検出
vFlag = 2;
DrawObject( object[1].trans, vFlag );
}
//バッファの内容を画面に表示 argSwapBuffers();
}
void mySetLight(void) {
GLfloat light_diffuse[] = { 0.9, 0.9, 0.9, 1.0 }; //拡散反射光 GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; //鏡面反射光 GLfloat light_ambient[] = { 0.3, 0.3, 0.3, 0.1 }; //環境光 GLfloat light_position[] = { 100.0, -200.0, 200.0, 0.0 }; //位置と種類
//光源の設定
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse ); //拡散反射光の設定 glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular ); //鏡面反射光の設定 glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient ); //環境光の設定
62
glLightfv( GL_LIGHT0, GL_POSITION, light_position ); //拡散反射光の設定
// glShadeModel( GL_SMOOTH ); //シェーディングの種類の設定
glEnable( GL_LIGHT0 ); //光源の有効化
}
void DrawObject( double patt_trans[3][4], int markV ) {
double gl_para[16];
static int k = 0; //描画するフレームの番号
//3Dオブジェクトを描画するための準備 argDrawMode3D();
argDraw3dCamera( 0, 0 );
//座標変換行列の適用
argConvGlpara( patt_trans, gl_para );
glMatrixMode( GL_MODELVIEW );
glLoadMatrixd( gl_para );
//3Dオブジェクトの描画
glClear( GL_DEPTH_BUFFER_BIT ); //Zバッファの初期化
glEnable( GL_DEPTH_TEST ); //陰面処理の適用
mySetLight(); //光源の設定
glEnable( GL_LIGHTING ); //光源の適用
if( markV == 0 ){
if( dFlag == 0 ){ //上がる
exTx2 = wmat4[0][3];
exTy2 = wmat4[1][3];
exTz2 = wmat4[2][3];
if( depth < 0.0 ){
depth += 1.0;
angle += 1.0;
exTz = depth;
exTz2 = depth;
63 }else{
if( angle2 < angle ){ //マーカーの方向へ向く aFlag = 1;
angle -= 1.0;
}else{
aFlag = 0;
dFlag = 1;
exTx2 = wmat4[0][3];
exTy2 = wmat4[1][3];
exTz2 = wmat4[2][3];
} }
}
else if( dFlag == 1 ){ //移動
exTx = exTx + ( wmat2[0][3] * 0.01 );
exTy = exTy + ( wmat2[1][3] * 0.01 );
exTz = exTz + ( wmat2[2][3] * 0.01 );
exTx2 = exTx2 - ( wmat4[0][3] * 0.01 );
exTy2 = exTy2 - ( wmat4[1][3] * 0.01 );
exTz2 = exTz2 - ( wmat4[2][3] * 0.01 );
}else if( dFlag == 2 ){
depth = exTz;
if(depth > -150){ //沈む
depth -= 1.0;
angle += 1.0;
exTz = depth;
exTz2 = depth;
}else{
exTx = 0.0;
exTy = 0.0;
exTx2 = wmat4[0][3];
exTy2 = wmat4[1][3];
dFlag = 0;
} }
64
//マーカー2まで行ったらマーカー1へ戻る if( wmat2[0][3] > 0 ){
if( exTx >= wmat2[0][3] ){
dFlag = 2;
} }else{
if( exTx < wmat2[0][3] ){
dFlag = 2;
} }
}
if( dFlag == 0 ){
//透明の箱
glPushMatrix();
if( markV == 2 )
glTranslatef( exTx2, exTy2, wmat2[2][3] );
glRotatef( 90.0, 1.0, 0.0, 0.0); //モデルを立たせる
mqoCallModel( box ); //モデルの描画
glPopMatrix();
}else if( dFlag == 2 ){
//透明の箱
glPushMatrix();
if( markV == 2 )
glTranslatef( exTx2, exTy2, wmat2[2][3] );
else
glTranslatef( exTx, exTy, wmat2[2][3] ); //モデルの平行 移動
glRotatef( 90.0, 1.0, 0.0, 0.0); //モデルを立たせる
mqoCallModel( box ); //モデルの描画
glPopMatrix();
}
//カボチャ
glPushMatrix();
glTranslatef( 0.0, 0.0, 40.0 ); //モデルの平行移動 if ( markV == 2 )
glTranslatef(exTx2, exTy2, exTz2);
else
65
glTranslatef(exTx, exTy, exTz);
glRotatef( 90.0, 1.0, 0.0, 0.0); //モデルを立たせる
glRotatef( angle, 0.0, 1.0, 0.0 ); //モデルを回転させる mqoCallSequence( mqo_seq, k ); //指定フレームの描画 glPopMatrix();
glDisable( GL_LIGHTING );
glDisable( GL_DEPTH_TEST );
//フレーム番号のカウント k++;
if( k >= n_frame ) k = 0;
}
void MouseEvent( int button, int state, int x, int y ) {
//入力状態を表示
printf("ボタン:%d 状態:%d 座標:(x,y)=(%d, %d) \n",button, state, x, y);
}
void KeyEvent( unsigned char key, int x, int y ) {
//ESCキーを入力したらアプリケーション終了 if( key == 0x1b ){
Cleanup();
exit(0);
} }
void Cleanup(void) {
arVideoCapStop(); //ビデオキャプチャの停止
arVideoClose(); //ビデオデバイスの終了
argCleanup(); //グラフィック処理の終了
if( image1 != NULL ) free(image1);
if( image2 != NULL ) free(image2);
if( image3 != NULL ) free(image3);
if( image4 != NULL ) free(image4);
66
mqoDeleteModel( box ); //モデルの削除
mqoDeleteSequence( mqo_seq ); //シーケンスの削除
mqoCleanup(); //GLMetaseqの終了処理
}
void Bitmapread(GLubyte **img_ptr, int* width_ptr, int* height_ptr, char *filename) {
FILE *fp;
int x, y, d;
int width, height, position = 0;
long t;
GLubyte *image;
fp = fopen(filename, "rb");
if ( fp == NULL ) { *width_ptr = 0; *height_ptr = 0; return; }
fseek(fp, 18, SEEK_SET);
fread(width_ptr, 4, 1, fp);
fread(height_ptr, 4, 1, fp);
width = *width_ptr;
height = *height_ptr;
image = (GLubyte*)malloc(3 * width * height * sizeof(GLubyte) );
if ( image == NULL ) { *width_ptr = 0; *height_ptr = 0; return; }
d = 4 - 3 * width % 4;
if ( d == 4 ) d = 0;
fseek(fp, 54, SEEK_SET);
for ( y = height - 1; y >= 0; y-- ) {
for ( x = 0; x < width; x++ ) {
fread((image + position + 2), 1, 1, fp);
fread((image + position + 1), 1, 1, fp);
fread((image + position), 1, 1, fp);
position += 3;
}
fread(&t, d, 1, fp);
67 }
fclose(fp);
*img_ptr = image;
}
BOOL CALLBACK dlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
switch( msg ){
case WM_INITDIALOG:
SetDlgItemText( hwndDlg, IDC_EDIT1, "1.0" );
break;
case WM_COMMAND:
switch( wParam ){
case IDOK:
char cbuf[20];
GetDlgItemText( hwndDlg, IDC_EDIT1, cbuf, 20 );
scaling = atof( cbuf );
if( scaling < 0.5 ) scaling = 1.0;
if( scaling > 5.0 ) scaling = 2.0;
EndDialog( hwndDlg, FALSE );
return TRUE;
case IDCANCEL:
EndDialog( hwndDlg, FALSE );
return TRUE;
} break;
case WM_CLOSE:
EndDialog( hwndDlg, FALSE );
return TRUE;
}
return FALSE;
}
68
Windows 対応にしたプログラム
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <AR\video.h>
#include <AR\param.h>
#include <AR\ar.h>
#include <AR/config.h>
#include <AR/gsub_lite.h>
#include "GLMetaseq.h"
#define APP_NAME TEXT("ARwindows")
/* カメラ構成*/
char *vconf = TEXT("Data\\WDM_camera_flipV.xml"); // 既定のカメラ構成
/* カメラパラメータ*/
char *cparam_name = TEXT("Data\\camera_para.dat"); // 既定のカメラパラメータ
/* パターンファイル*/
char *patt_name = TEXT("Data\\patt.ichi"); // パターンファイル名
/* モデル*/
char *seq_name = TEXT( "Sequence\\walk_%d.mqo" ); //カボチャ歩く
// ============================================================================
// Constants
// ============================================================================
#define VIEW_SCALEFACTOR 0.025 // 1.0 ARToolKit unit becomes 0.025 of my OpenGL units.
#define VIEW_DISTANCE_MIN 0.1 // Objects closer to the camera than this will not be displayed.
69
#define VIEW_DISTANCE_MAX 100.0 // Objects further away from the camera than this will not be displayed.
// Marker detection.
static int gARTThreshhold = 100;
// Transformation matrix retrieval.
static double gPatt_width = 80.0; // Per-marker, but we are using only 1 marker.
static double gPatt_centre[2] = {0.0, 0.0}; // Per-marker, but we are using only 1 marker.
double gPatt_trans[3][4]; // Per-marker, but we are using only 1 marker.
int gPatt_found = FALSE; // Per-marker, but we are using only 1 marker.
int gPatt_id; // Per-marker, but we are
using only 1 marker.
// Drawing.
ARParam gARTCparam;
ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
MQO_SEQUENCE mqo_seq; //シーケンス
int n_frame = 42; //フレーム数
int xsize, ysize;
// ============================================================================
// Functions
// ============================================================================
// Something to look at, draw a rotating colour cube.
static void DrawFigure(void) {
static int k=0; //フレーム番号
glPushMatrix(); // Save world coordinate system.
glScalef( 0.04, 0.04, 0.04 );
70
glTranslatef(0.0, 0.0, 40.0); // Place base of cube on marker surface.
glRotatef( 90.0, 1.0, 0.0, 0.0 );
mqoCallSequence(mqo_seq, k); // Draw the cube.
glPopMatrix(); // Restore world coordinate system.
//フレーム番号のカウント k++;
if( k >= n_frame ) k = 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
HDC hdc;
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
int pfdID;
BOOL bResult;
static HGLRC m_hGLRC;
RECT winsize;
ARParam wparam; // カメラパラメータ
static ARUint8 *gARTImage; // カメラ画像
static ARMarkerInfo *marker_info; // マーカー検出用の情報
static int marker_num; // マーカーらしき部分の個数
static int isFirst = 1;
GLdouble p[16], m[16];
PAINTSTRUCT ps;
int j, k;