ブラウザ上でゲーム開発を行える「Code.9leap.net」,β版サービスが始まる
これにあたり、「code.9leapカスタム・チュートリアルチャレンジ!」というコンテストが開催されました。
っということで、私もチャレンジしてみようと思います!
私がenchant.jsで最初に悩んだところは画面遷移でした。
ということで、そのあたりのチュートリアルを作ってみました 。
ゲームの基本「タイトル画面 → プレイ画面 → エンド画面」の流れを簡単に説明しています。
かっしぃの日々のメモ帳です。 気づいたことや思ったこと、プログラミングのコツ、 最近気になることなどをメモしてます。 Twitter http://twitter.com/kassy708
//初期化 | |
int init(){ | |
//Kinectの初期化関数 | |
NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON ); | |
//各ハンドルの設定 | |
m_hNextImageFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pImageStreamHandle = NULL; | |
m_hNextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pDepthStreamHandle = NULL; | |
//深度センサストリームの設定 | |
HRESULT hr; | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextImageFrameEvent , &m_pImageStreamHandle ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_320x240 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#endif | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
return 1; | |
} |
HRESULT NuiInitialize( DWORD dwFlags )
//Kinectの初期化関数 | |
NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON ); |
//各ハンドルの設定 | |
m_hNextImageFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pImageStreamHandle = NULL; | |
m_hNextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pDepthStreamHandle = NULL; | |
//深度センサストリームの設定 | |
HRESULT hr; | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextImageFrameEvent , &m_pImageStreamHandle ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_320x240 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#else if KKINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#endif | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 |
KINECT_DEPTH_WIDTHを#defineで事前に定義して、ここで条件分岐しています。
KinectSDKはBetaの時はDepth画像の解像度を320x240しか設定できなかったのですがconst NUI_IMAGE_FRAME *pImageFrame = NULL; | |
//次のRGBフレームが来るまで待機 | |
WaitForSingleObject(m_hNextImageFrameEvent,INFINITE); | |
HRESULT hr = NuiImageStreamGetNextFrame(m_pImageStreamHandle, 30 , &pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
//Todo:RGB画像を処理 | |
//次のDepthフレームが来るまで待機 | |
WaitForSingleObject(m_hNextDepthFrameEvent,INFINITE); | |
HRESULT hr = NuiImageStreamGetNextFrame(m_pDepthStreamHandle, 30 , &pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
//Todo:Depth画像を処理 |
int GetImage(cv::Mat &image,HANDLE frameEvent,HANDLE streamHandle){ | |
//フレームを入れるクラス | |
const NUI_IMAGE_FRAME *pImageFrame = NULL; | |
//次のRGBフレームが来るまで待機 | |
WaitForSingleObject(frameEvent,INFINITE); | |
HRESULT hr = NuiImageStreamGetNextFrame(streamHandle, 30 , &pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
//フレームから画像データの取得 | |
INuiFrameTexture * pTexture = pImageFrame->pFrameTexture; | |
NUI_LOCKED_RECT LockedRect; | |
pTexture->LockRect( 0, &LockedRect, NULL, 0 ); | |
if( LockedRect.Pitch != 0 ){ | |
//pBitsに画像データが入っている | |
BYTE *pBuffer = (BYTE*) LockedRect.pBits; | |
memcpy(image.data,pBuffer,image.step * image.rows); | |
} | |
hr = NuiImageStreamReleaseFrame( streamHandle, pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
return 0; | |
} |
if(GetImage(image,m_hNextImageFrameEvent,m_pImageStreamHandle)==-1){ | |
printf("Failed get RGB image\n"); | |
} | |
if(GetImage(depth,m_hNextDepthFrameEvent,m_pDepthStreamHandle)==-1){ | |
printf("Failed get depth image\n"); | |
} |
//3次元ポイントクラウドのための座標変換 | |
void retrievePointCloudMap(Mat &depth,Mat &pointCloud_XYZ){ | |
unsigned short* dp = (unsigned short*)depth.data; | |
Point3f *point = (Point3f *)pointCloud_XYZ.data; | |
for(int y = 0;y < depth.rows;y++){ | |
for(int x = 0;x < depth.cols;x++, dp++,point++){ | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
Vector4 RealPoints = NuiTransformDepthImageToSkeleton(x,y,*dp); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
Vector4 RealPoints = NuiTransformDepthImageToSkeleton(x,y,*dp, NUI_IMAGE_RESOLUTION_640x480); | |
#endif | |
point->x = RealPoints.x; | |
point->y = RealPoints.y; | |
point->z = RealPoints.z; | |
} | |
} | |
} |
//ポイントクラウド描画 | |
void drawPointCloud(Mat &rgbImage,Mat &pointCloud_XYZ){ | |
static int x,y; | |
glPointSize(2); | |
glBegin(GL_POINTS); | |
uchar *p; | |
Point3f *point = (Point3f*)pointCloud_XYZ.data; | |
LONG colorX,colorY; | |
for(y = 0;y < pointCloud_XYZ.rows;y++){ | |
for(x = 0;x < pointCloud_XYZ.cols;x++,point++){ | |
if(point->z == 0) | |
continue; | |
//ズレを直す | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
NuiImageGetColorPixelCoordinatesFromDepthPixel(NUI_IMAGE_RESOLUTION_640x480,NULL,x,y,0,&colorX,&colorY); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution(NUI_IMAGE_RESOLUTION_640x480,NUI_IMAGE_RESOLUTION_640x480,NULL,x,y,0,&colorX,&colorY); | |
#endif | |
//画像内の場合 | |
if(0 <= colorX && colorX <= rgbImage.cols && 0 <= colorY && colorY <= rgbImage.rows){ | |
p = &rgbImage.data[colorY * rgbImage.step + colorX * rgbImage.channels()]; | |
glColor3ubv(p); | |
glVertex3f(point->x,point->y,point->z); | |
} | |
} | |
} | |
glEnd(); | |
} |
/** | |
author @kassy708 | |
OpenGLとKinect SDK v1.0を使ったポイントクラウド | |
*/ | |
#include<Windows.h> | |
#include<NuiApi.h> //KinectSDK利用時にinclude | |
#pragma comment(lib,"Kinect10.lib") | |
#include <GL/glut.h> | |
#include <opencv2/opencv.hpp> | |
#ifdef _DEBUG | |
//Debugモードの場合 | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220d.lib") // opencv_core | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220d.lib") // opencv_imgproc | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib") // opencv_highgui | |
#else | |
//Releaseモードの場合 | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220.lib") // opencv_core | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220.lib") // opencv_imgproc | |
#pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220.lib") // opencv_highgui | |
#endif | |
using namespace cv; | |
//openNIのための宣言・定義 | |
//マクロ定義 | |
#define KINECT_IMAGE_WIDTH 640 | |
#define KINECT_IMAGE_HEGIHT 480 | |
#define KINECT_DEPTH_WIDTH 640 | |
#define KINECT_DEPTH_HEGIHT 480 | |
//#define KINECT_DEPTH_WIDTH 320 | |
//#define KINECT_DEPTH_HEGIHT 240 | |
Mat image(KINECT_IMAGE_HEGIHT,KINECT_IMAGE_WIDTH,CV_8UC4); | |
Mat depth(KINECT_DEPTH_HEGIHT,KINECT_DEPTH_WIDTH,CV_16UC1); | |
//ポイントクラウドの座標 | |
Mat pointCloud_XYZ(KINECT_DEPTH_HEGIHT,KINECT_DEPTH_WIDTH,CV_32FC3,cv::Scalar::all(0)); | |
void retrievePointCloudMap(Mat &depth,Mat &pointCloud_XYZ); //3次元ポイントクラウドのための座標変換 | |
void drawPointCloud(Mat &rgbImage,Mat &pointCloud_XYZ); //ポイントクラウド描画 | |
//画像データを取得する関数 | |
int GetImage(cv::Mat &image,HANDLE frameEvent,HANDLE streamHandle); | |
//openGLのための宣言・定義 | |
//---変数宣言--- | |
int FormWidth = 640; | |
int FormHeight = 480; | |
int mButton; | |
float twist, elevation, azimuth; | |
float cameraDistance = 0,cameraX = 0,cameraY = 0; | |
int xBegin, yBegin; | |
//---マクロ定義--- | |
#define glFovy 45 //視角度 | |
#define glZNear 1.0 //near面の距離 | |
#define glZFar 150.0 //far面の距離 | |
void polarview(); //視点変更 | |
//ハンドル | |
HANDLE m_hNextImageFrameEvent; | |
HANDLE m_hNextDepthFrameEvent; | |
HANDLE m_pImageStreamHandle; | |
HANDLE m_pDepthStreamHandle; | |
//描画 | |
void display(){ | |
// clear screen and depth buffer | |
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | |
// Reset the coordinate system before modifying | |
glLoadIdentity(); | |
glEnable(GL_DEPTH_TEST); //「Zバッファ」を有効 | |
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); //視点の向き設定 | |
if(GetImage(image,m_hNextImageFrameEvent,m_pImageStreamHandle)==-1) | |
return; | |
if(GetImage(depth,m_hNextDepthFrameEvent,m_pDepthStreamHandle)==-1) | |
return; | |
//3次元ポイントクラウドのための座標変換 | |
retrievePointCloudMap(depth,pointCloud_XYZ); | |
//視点の変更 | |
polarview(); | |
imshow("image",image); | |
imshow("depth",depth); | |
//RGBAからBGRAに変換 | |
cvtColor(image,image,CV_RGBA2BGRA); | |
//ポイントクラウド | |
drawPointCloud(image,pointCloud_XYZ); | |
glFlush(); | |
glutSwapBuffers(); | |
} | |
//初期化 | |
int init(){ | |
//Kinectの初期化関数 | |
NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON ); | |
//各ハンドルの設定 | |
m_hNextImageFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pImageStreamHandle = NULL; | |
m_hNextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
m_pDepthStreamHandle = NULL; | |
//深度センサストリームの設定 | |
HRESULT hr; | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextImageFrameEvent , &m_pImageStreamHandle ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_320x240 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX , NUI_IMAGE_RESOLUTION_640x480 , 0 , 2 , m_hNextDepthFrameEvent , &m_pDepthStreamHandle ); | |
#endif | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
return 1; | |
} | |
// アイドル時のコールバック | |
void idle(){ | |
//再描画要求 | |
glutPostRedisplay(); | |
} | |
//ウィンドウのサイズ変更 | |
void reshape (int width, int height){ | |
FormWidth = width; | |
FormHeight = height; | |
glViewport (0, 0, (GLsizei)width, (GLsizei)height); | |
glMatrixMode (GL_PROJECTION); | |
glLoadIdentity (); | |
//射影変換行列の指定 | |
gluPerspective (glFovy, (GLfloat)width / (GLfloat)height,glZNear,glZFar); | |
glMatrixMode (GL_MODELVIEW); | |
} | |
//マウスの動き | |
void motion(int x, int y){ | |
int xDisp, yDisp; | |
xDisp = x - xBegin; | |
yDisp = y - yBegin; | |
switch (mButton) { | |
case GLUT_LEFT_BUTTON: | |
azimuth += (float) xDisp/2.0; | |
elevation -= (float) yDisp/2.0; | |
break; | |
case GLUT_MIDDLE_BUTTON: | |
cameraX -= (float) xDisp/40.0; | |
cameraY += (float) yDisp/40.0; | |
break; | |
case GLUT_RIGHT_BUTTON: | |
cameraDistance += xDisp/40.0; | |
break; | |
} | |
xBegin = x; | |
yBegin = y; | |
} | |
//マウスの操作 | |
void mouse(int button, int state, int x, int y){ | |
if (state == GLUT_DOWN) { | |
switch(button) { | |
case GLUT_RIGHT_BUTTON: | |
case GLUT_MIDDLE_BUTTON: | |
case GLUT_LEFT_BUTTON: | |
mButton = button; | |
break; | |
} | |
xBegin = x; | |
yBegin = y; | |
} | |
} | |
//視点変更 | |
void polarview(){ | |
glTranslatef( cameraX, cameraY, cameraDistance); | |
glRotatef( -twist, 0.0, 0.0, 1.0); | |
glRotatef( -elevation, 1.0, 0.0, 0.0); | |
glRotatef( -azimuth, 0.0, 1.0, 0.0); | |
} | |
//メイン | |
int main(int argc, char *argv[]){ | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB); | |
glutInitWindowSize(FormWidth, FormHeight); | |
glutCreateWindow(argv[0]); | |
//コールバック | |
glutReshapeFunc (reshape); | |
glutDisplayFunc(display); | |
glutIdleFunc(idle); | |
glutMouseFunc(mouse); | |
glutMotionFunc(motion); | |
init(); | |
glutMainLoop(); | |
NuiShutdown(); | |
return 0; | |
} | |
int GetImage(cv::Mat &image,HANDLE frameEvent,HANDLE streamHandle){ | |
//フレームを入れるクラス | |
const NUI_IMAGE_FRAME *pImageFrame = NULL; | |
//次のRGBフレームが来るまで待機 | |
WaitForSingleObject(frameEvent,INFINITE); | |
HRESULT hr = NuiImageStreamGetNextFrame(streamHandle, 30 , &pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
//フレームから画像データの取得 | |
INuiFrameTexture * pTexture = pImageFrame->pFrameTexture; | |
NUI_LOCKED_RECT LockedRect; | |
pTexture->LockRect( 0, &LockedRect, NULL, 0 ); | |
if( LockedRect.Pitch != 0 ){ | |
//pBitsに画像データが入っている | |
BYTE *pBuffer = (BYTE*) LockedRect.pBits; | |
memcpy(image.data,pBuffer,image.step * image.rows); | |
} | |
hr = NuiImageStreamReleaseFrame( streamHandle, pImageFrame ); | |
if( FAILED( hr ) ) | |
return -1;//取得失敗 | |
return 0; | |
} | |
//ポイントクラウド描画 | |
void drawPointCloud(Mat &rgbImage,Mat &pointCloud_XYZ){ | |
static int x,y; | |
glPointSize(2); | |
glBegin(GL_POINTS); | |
uchar *p; | |
Point3f *point = (Point3f*)pointCloud_XYZ.data; | |
LONG colorX,colorY; | |
for(y = 0;y < pointCloud_XYZ.rows;y++){ | |
for(x = 0;x < pointCloud_XYZ.cols;x++,point++){ | |
if(point->z == 0) | |
continue; | |
//ズレを直す | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
NuiImageGetColorPixelCoordinatesFromDepthPixel(NUI_IMAGE_RESOLUTION_640x480,NULL,x,y,0,&colorX,&colorY); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution(NUI_IMAGE_RESOLUTION_640x480,NUI_IMAGE_RESOLUTION_640x480,NULL,x,y,0,&colorX,&colorY); | |
#endif | |
//画像内の場合 | |
if(0 <= colorX && colorX <= rgbImage.cols && 0 <= colorY && colorY <= rgbImage.rows){ | |
p = &rgbImage.data[colorY * rgbImage.step + colorX * rgbImage.channels()]; | |
glColor3ubv(p); | |
glVertex3f(point->x,point->y,point->z); | |
} | |
} | |
} | |
glEnd(); | |
} | |
//3次元ポイントクラウドのための座標変換 | |
void retrievePointCloudMap(Mat &depth,Mat &pointCloud_XYZ){ | |
unsigned short* dp = (unsigned short*)depth.data; | |
Point3f *point = (Point3f *)pointCloud_XYZ.data; | |
for(int y = 0;y < depth.rows;y++){ | |
for(int x = 0;x < depth.cols;x++, dp++,point++){ | |
#if KINECT_DEPTH_WIDTH == 320 | |
//奥行き画像の解像度が320x240の場合 | |
Vector4 RealPoints = NuiTransformDepthImageToSkeleton(x,y,*dp); | |
#else if KINECT_DEPTH_WIDTH == 640 | |
//奥行き画像の解像度が640x480の場合 | |
Vector4 RealPoints = NuiTransformDepthImageToSkeleton(x,y,*dp, NUI_IMAGE_RESOLUTION_640x480); | |
#endif | |
point->x = RealPoints.x; | |
point->y = RealPoints.y; | |
point->z = RealPoints.z; | |
} | |
} | |
} |
enchant.PhyPolygonSprite(width, height, vertexs, type, density, friction, restitution, awake)
var width = 20; var height = 50; var vertexs = new Array( new b2Vec2(-width / 2, -height / 2), new b2Vec2(width / 2, -height / 2), new b2Vec2(width / 2, height / 2), new b2Vec2(-width / 2, height / 2)); var phyPolygonSprite = new PhyPolygonSprite(width, height, vertexs, DYNAMIC_SPRITE, 1.0, 0.1, 0.2, true); game.rootScene.addChild(phyPolygonSprite); // シーンに追加
var vertexCount = 5; var radius = 20; var vertexs = new Array(); for (var i = 0; i < vertexCount; i++) { vertexs[i] = new b2Vec2(radius * Math.cos(2 * Math.PI / vertexCount * i), radius * Math.sin(2 * Math.PI / vertexCount * i)); } var phyPolygonSprite = new PhyPolygonSprite(radius * 2, radius * 2, vertexs, DYNAMIC_SPRITE, 1.0, 0.1, 0.2, true); game.rootScene.addChild(phyPolygonSprite); // シーンに追加
//軸 var axis = new PhyCircleSprite(8, STATIC_SPRITE); axis.position = { x: 160, y: 160 }; game.rootScene.addChild(axis); // シーンに追加 //ボール生成 var ball = new PhyCircleSprite(8, DYNAMIC_SPRITE); ball.position = { x: 100, y: 250 }; game.rootScene.addChild(ball); // シーンに追加 //距離ジョイント var joint = new PhyDistanceJoint(axis, ball);
//軸 var axis = new PhyCircleSprite(8, STATIC_SPRITE); axis.position = { x: 160, y: 160 }; game.rootScene.addChild(axis); // シーンに追加 //ボール生成 var ball = new PhyCircleSprite(8, DYNAMIC_SPRITE); ball.position = { x: 100, y: 250 }; game.rootScene.addChild(ball); // シーンに追加 //距離ジョイント var joint = new PhyRevoluteJoint(axis, ball); joint.enableMotor = true; joint.maxMotorTorque = 100; joint.motorSpeed = 90;
var box = new PhyBoxSprite(16, 8, DYNAMIC_SPRITE, 1.0, 0.5, 0.2, true); box.position = { x: game.width * 2 / 3, y: game.height / 2 }; var prismaticAxis = new b2Vec2(1.0, 0); //x軸にスライドを設定(右が正の値) //スライドジョイント var prismaticJoint = new PhyPrismaticJoint(box, prismaticAxis); //スライドオブジェクトにモーター機能を持たせる場合 //prismaticJoint.enableMotor = true; //モータの有効化 //prismaticJoint.maxMotorForce = 100.0; //モータの最大力を設定 //prismaticJoint.motorSpeed = 50; //モータの速度を設定
var ball1 = new PhyCircleSprite(8, DYNAMIC_SPRITE); ball1.position = { x: 80, y: 160 }; var ball2 = new PhyCircleSprite(8, DYNAMIC_SPRITE); ball2.position = { x: 240, y: 160 }; //滑車ジョイント var pulleyJoint = new PhyPulleyJoint(ball1, ball2, new b2Vec2(80, 100), new b2Vec2(240, 100), 1);
GLCapture glCapture; void init(){ //glCaptureの設定 glCapture.setWriteFile("output.avi"); } void display(){ glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //~描画するプログラム~ glFlush(); glutSwapBuffers(); //動画ファイルに書き込み glCapture.write(); }と、こんな感じです。
context.FindExistingNode(XN_NODE_TYPE_USER, userGenerator); xn::SkeletonCapability skeleton = userGenerator.GetSkeletonCap(); // ユーザー認識のコールバックを登録 // キャリブレーションのコールバックを登録 XnCallbackHandle userCallbacks, calibrationCallbacks; userGenerator.RegisterUserCallbacks(&::UserDetected, 0, 0, userCallbacks); skeleton.RegisterCalibrationCallbacks( 0, &::CalibrationEnd, 0, calibrationCallbacks ); skeleton.SetSkeletonProfile(XN_SKEL_PROFILE_ALL);
// ユーザー検出 void XN_CALLBACK_TYPE UserDetected( xn::UserGenerator& generator, XnUserID nId, void* pCookie ) { printf("ユーザID%d 検出 %d人目\n",nId,generator.GetNumberOfUsers()); generator.GetSkeletonCap().RequestCalibration(nId, TRUE); } // キャリブレーションの終了 void XN_CALLBACK_TYPE CalibrationEnd(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie) { if ( bSuccess ) { printf("ユーザID%d キャリブレーション成功\n",nId); capability.StartTracking(nId); } else { printf("ユーザID%d キャリブレーション失敗\n",nId); } }
XnUserID aUsers[15]; XnUInt16 nUsers = 15; userGenerator.GetUsers(aUsers, nUsers); for (int i = 0; i < nUsers; ++i){ if (userGenerator.GetSkeletonCap().IsTracking(aUsers[i])){ XnSkeletonJointPosition joint; //aUsers[i]の頭部位置をjointに格納 userGenerator.GetSkeletonCap().GetSkeletonJointPosition(aUsers[i], XN_SKEL_HEAD, joint); } }
#include <GL/glut.h> #include <opencv2/opencv.hpp> #ifdef _DEBUG //Debugモードの場合 #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220d.lib") // opencv_core #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220d.lib") // opencv_imgproc #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib") // opencv_highgui #else //Releaseモードの場合 #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_core220.lib") // opencv_core #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_imgproc220.lib") // opencv_imgproc #pragma comment(lib,"C:\\OpenCV2.2\\lib\\opencv_highgui220.lib") // opencv_highgui #endif #include <XnCppWrapper.h> #pragma comment(lib,"C:/Program files/OpenNI/Lib/openNI.lib") #define SAMPLE_XML_PATH "C:/Program Files/OpenNI/Data/SamplesConfig.xml" using namespace cv; using namespace xn; //openNIのための宣言・定義 //マクロ定義 #define KINECT_IMAGE_WIDTH 640 #define KINECT_IMAGE_HEGIHT 480 #define KINECT_DEPTH_WIDTH 640 #define KINECT_DEPTH_HEGIHT 480 DepthGenerator depthGenerator;// depth context ImageGenerator imageGenerator;//image context UserGenerator userGenerator; DepthMetaData depthMD; ImageMetaData imageMD; Context context; //トラッキングの際のコールバック void XN_CALLBACK_TYPE UserDetected( xn::UserGenerator& generator, XnUserID nId, void* pCookie ); void XN_CALLBACK_TYPE CalibrationEnd(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie); Mat image(480,640,CV_8UC3); Mat depth(480,640,CV_16UC1); //ポイントクラウドの座標 Mat pointCloud_XYZ(480,640,CV_32FC3,cv::Scalar::all(0)); void retrievePointCloudMap(Mat &depth,Mat &pointCloud_XYZ); //3次元ポイントクラウドのための座標変換 void drawPointCloud(Mat &rgbImage,Mat &pointCloud_XYZ); //ポイントクラウド描画 void drawUserJoint(); //ユーザの関節を描画 void DrawLimb(XnUserID player, XnSkeletonJoint eJoint1, XnSkeletonJoint eJoint2); void DrawJoint(XnUserID player, XnSkeletonJoint eJoint1); //openGLのための宣言・定義 //---変数宣言--- int FormWidth = 640; int FormHeight = 480; int mButton; float twist, elevation, azimuth; float cameraDistance = 0,cameraX = 0,cameraY = 0; int xBegin, yBegin; //---マクロ定義--- #define glFovy 45 //視角度 #define glZNear 1.0 //near面の距離 #define glZFar 150.0 //far面の距離 void polarview(); //視点変更 //描画 void display(){ // clear screen and depth buffer glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Reset the coordinate system before modifying glLoadIdentity(); glEnable(GL_DEPTH_TEST); //「Zバッファ」を有効 gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); //視点の向き設定 //wait and error processing context.WaitAnyUpdateAll(); imageGenerator.GetMetaData(imageMD); depthGenerator.GetMetaData(depthMD); depthGenerator.GetAlternativeViewPointCap().SetViewPoint(imageGenerator);//ズレを補正 memcpy(image.data,imageMD.Data(),image.step * image.rows); //イメージデータを格納 memcpy(depth.data,depthMD.Data(),depth.step * depth.rows); //深度データを格納 //3次元ポイントクラウドのための座標変換 retrievePointCloudMap(depth,pointCloud_XYZ); //視点の変更 polarview(); //ポイントクラウド drawPointCloud(image,pointCloud_XYZ); //関節の描画 drawUserJoint(); //convert color space RGB2BGR cvtColor(image,image,CV_RGB2BGR); imshow("image",image); imshow("depth",depth); glFlush(); glutSwapBuffers(); } //初期化 void init(){ context.InitFromXmlFile(SAMPLE_XML_PATH); context.FindExistingNode(XN_NODE_TYPE_DEPTH, depthGenerator); context.FindExistingNode(XN_NODE_TYPE_IMAGE, imageGenerator); context.FindExistingNode(XN_NODE_TYPE_USER, userGenerator); if (!userGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON)) { // スケルトン・トラッキングをサポートしているか確認 printf("ユーザー検出をサポートしてません\n"); } // キャリブレーションにポーズが必要 xn::SkeletonCapability skeleton = userGenerator.GetSkeletonCap(); if ( skeleton.NeedPoseForCalibration() ) { printf("このOpenNIのバージョンはポーズ無しには対応していません\n"); } // ユーザー認識のコールバックを登録 // キャリブレーションのコールバックを登録 XnCallbackHandle userCallbacks, calibrationCallbacks; userGenerator.RegisterUserCallbacks(&::UserDetected, 0, 0, userCallbacks); skeleton.RegisterCalibrationCallbacks( 0, &::CalibrationEnd, 0, calibrationCallbacks ); skeleton.SetSkeletonProfile(XN_SKEL_PROFILE_ALL); } // アイドル時のコールバック void idle(){ //再描画要求 glutPostRedisplay(); } //ウィンドウのサイズ変更 void reshape (int width, int height){ FormWidth = width; FormHeight = height; glViewport (0, 0, (GLsizei)width, (GLsizei)height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); //射影変換行列の指定 gluPerspective (glFovy, (GLfloat)width / (GLfloat)height,glZNear,glZFar); glMatrixMode (GL_MODELVIEW); } //マウスの動き void motion(int x, int y){ int xDisp, yDisp; xDisp = x - xBegin; yDisp = y - yBegin; switch (mButton) { case GLUT_LEFT_BUTTON: azimuth += (float) xDisp/2.0; elevation -= (float) yDisp/2.0; break; case GLUT_MIDDLE_BUTTON: cameraX -= (float) xDisp/40.0; cameraY += (float) yDisp/40.0; break; case GLUT_RIGHT_BUTTON: cameraDistance += (float) xDisp/40.0; break; } xBegin = x; yBegin = y; } //マウスの操作 void mouse(int button, int state, int x, int y){ if (state == GLUT_DOWN) { switch(button) { case GLUT_RIGHT_BUTTON: case GLUT_MIDDLE_BUTTON: case GLUT_LEFT_BUTTON: mButton = button; break; } xBegin = x; yBegin = y; } } //視点変更 void polarview(){ glTranslatef( cameraX, cameraY, cameraDistance); glRotatef( -twist, 0.0, 0.0, 1.0); glRotatef( -elevation, 1.0, 0.0, 0.0); glRotatef( -azimuth, 0.0, 1.0, 0.0); } //メイン int main(int argc, char *argv[]){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(FormWidth, FormHeight); glutCreateWindow(argv[0]); //コールバック glutReshapeFunc (reshape); glutDisplayFunc(display); glutIdleFunc(idle); glutMouseFunc(mouse); glutMotionFunc(motion); init(); glutMainLoop(); context.Shutdown(); return 0; } //ポイントクラウド描画 void drawPointCloud(Mat &rgbImage,Mat &pointCloud_XYZ){ static int x,y; glPointSize(2); glBegin(GL_POINTS); uchar *p = rgbImage.data; Point3f *point = (Point3f*)pointCloud_XYZ.data; for(y = 0;y < KINECT_DEPTH_HEGIHT;y++){ for(x = 0;x < KINECT_DEPTH_WIDTH;x++,p += 3,point++){ if(point->z == 0) continue; glColor3ubv(p); glVertex3f(point->x,point->y,point->z); } } glEnd(); } //3次元ポイントクラウドのための座標変換 void retrievePointCloudMap(Mat &depth,Mat &pointCloud_XYZ){ static const int size = KINECT_DEPTH_HEGIHT * KINECT_DEPTH_WIDTH; static XnPoint3D proj[size] = {0}; static int x,y; XnPoint3D *p = proj; unsigned short* dp = (unsigned short*)depth.data; for(y = 0; y < KINECT_DEPTH_HEGIHT; y++ ){ for(x = 0; x < KINECT_DEPTH_WIDTH; x++, p++, dp++){ p->X = x; p->Y = y; p->Z = *dp * 0.001f; // from mm to meters } } //現実座標に変換 depthGenerator.ConvertProjectiveToRealWorld(size, proj, (XnPoint3D*)pointCloud_XYZ.data); } //人物の骨格を描画 void drawUserJoint(){ XnUserID aUsers[15]; XnUInt16 nUsers = 15; userGenerator.GetUsers(aUsers, nUsers); for (int i = 0; i < nUsers; ++i){ if (userGenerator.GetSkeletonCap().IsTracking(aUsers[i])){ //各関節に点を打つ glPointSize(5); glBegin(GL_POINTS); glColor4f(0,255,0, 1); for(int Joint = XN_SKEL_HEAD;Joint < XN_SKEL_RIGHT_FOOT + 1;Joint++) DrawJoint(aUsers[i],(XnSkeletonJoint)Joint); glEnd(); //各肢に線を書く glBegin(GL_LINES); glColor4f(255,0,0, 1); DrawLimb(aUsers[i], XN_SKEL_HEAD, XN_SKEL_NECK); DrawLimb(aUsers[i], XN_SKEL_NECK, XN_SKEL_LEFT_SHOULDER); DrawLimb(aUsers[i], XN_SKEL_LEFT_SHOULDER, XN_SKEL_LEFT_ELBOW); DrawLimb(aUsers[i], XN_SKEL_LEFT_ELBOW, XN_SKEL_LEFT_HAND); DrawLimb(aUsers[i], XN_SKEL_NECK, XN_SKEL_RIGHT_SHOULDER); DrawLimb(aUsers[i], XN_SKEL_RIGHT_SHOULDER, XN_SKEL_RIGHT_ELBOW); DrawLimb(aUsers[i], XN_SKEL_RIGHT_ELBOW, XN_SKEL_RIGHT_HAND); DrawLimb(aUsers[i], XN_SKEL_LEFT_SHOULDER, XN_SKEL_TORSO); DrawLimb(aUsers[i], XN_SKEL_RIGHT_SHOULDER, XN_SKEL_TORSO); DrawLimb(aUsers[i], XN_SKEL_TORSO, XN_SKEL_LEFT_HIP); DrawLimb(aUsers[i], XN_SKEL_LEFT_HIP, XN_SKEL_LEFT_KNEE); DrawLimb(aUsers[i], XN_SKEL_LEFT_KNEE, XN_SKEL_LEFT_FOOT); DrawLimb(aUsers[i], XN_SKEL_TORSO, XN_SKEL_RIGHT_HIP); DrawLimb(aUsers[i], XN_SKEL_RIGHT_HIP, XN_SKEL_RIGHT_KNEE); DrawLimb(aUsers[i], XN_SKEL_RIGHT_KNEE, XN_SKEL_RIGHT_FOOT); DrawLimb(aUsers[i], XN_SKEL_LEFT_HIP, XN_SKEL_RIGHT_HIP); glEnd(); } } } void DrawJoint(XnUserID player, XnSkeletonJoint eJoint){ XnSkeletonJointPosition joint; userGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint, joint); //信頼性の低い場合描画しない if (joint.fConfidence < 0.5) return; glVertex3f(joint.position.X* 0.001f, joint.position.Y* 0.001f, joint.position.Z* 0.001f); } void DrawLimb(XnUserID player, XnSkeletonJoint eJoint1, XnSkeletonJoint eJoint2){ XnSkeletonJointPosition joint1, joint2; userGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint1, joint1); userGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint2, joint2); //信頼性の低い場合描画しない if (joint1.fConfidence < 0.5 || joint2.fConfidence < 0.5) return; glVertex3f(joint1.position.X* 0.001f, joint1.position.Y* 0.001f, joint1.position.Z* 0.001f); glVertex3f(joint2.position.X* 0.001f, joint2.position.Y* 0.001f, joint2.position.Z* 0.001f); } // ユーザー検出 void XN_CALLBACK_TYPE UserDetected( xn::UserGenerator& generator, XnUserID nId, void* pCookie ) { printf("ユーザID%d 検出 %d人目\n",nId,generator.GetNumberOfUsers()); generator.GetSkeletonCap().RequestCalibration(nId, TRUE); } // キャリブレーションの終了 void XN_CALLBACK_TYPE CalibrationEnd(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie) { if ( bSuccess ) { printf("ユーザID%d キャリブレーション成功\n",nId); capability.StartTracking(nId); } else { printf("ユーザID%d キャリブレーション失敗\n",nId); } }