ofxNetworkを使ってiPhoneとMacでTCP通信 その2

ofxNetworkを使ってiPhoneとMacでTCP通信 その2

May 9, 2010
前回、iPhoneとMacの間でTCP通信を行い、加速度センサーの値を送受信するところまでできたので、今回はその値を使って3Dオブジェクトを動かしてみます。

前回のサンプルでは、以下のように加速度センサーの値の下二ケタを取り出しカンマ区切りで連結していました。

if(weConnected){
msgTx =
ofToString( ofxAccelerometer.getForce().x, 2) + "," +
ofToString( ofxAccelerometer.getForce().y, 2) + "," +
ofToString( ofxAccelerometer.getForce().z, 2);
}


これをサーバー側で受信した後で、それぞれの値ごとに分割して格納します。networkTcpServerExampleのプロジェクトを開き、testApp.cppを開いてみます。

setup()で、TCPをセットアップし、

//setup the server to listen on 11999
TCP.setup(11999);

draw()の中の以下の部分で値を受け取っています。

//we only want to update the text we have recieved there is data
string str = TCP.receive(i);


ここで、strは「0.00,0.00,0.00」のような文字列になっているはずなので、ofSplitStringを使って分割しvectorとして格納します。それをFloatにしてから、角度に変換します。

// カンマ区切りで分割。
vector dataStr = ofSplitString( str, "," );

//Floatに変換して格納。
data.x = ofToFloat( dataStr[0] );
data.y = ofToFloat( dataStr[1] );
data.z = ofToFloat( dataStr[2] );

// 角度に変換
ofPoint rotation = 0.0;
rotation.x = asin(data.y) * ( 180.0/PI );
rotation.y = 0.0;
rotation.z = asin(data.x) * ( 180.0/PI );


さて、これで加速度センサーの値を受け取る事はできました。次に3Dオブジェクトの読み込みます。方法は以下を参考にしてください。
Shadeで作った3Dモデルをofx3DModelLoaderで読み込んでみる

読み込んだモデルに対し、先ほどの角度をセットします。

modelObj.setRotation( 0, rotation.x, 1, 0, 0 );
modelObj.setRotation( 1, rotation.y, 0, 1, 0 );
modelObj.setRotation( 2, rotation.z, 0, 0, 1 );


ざっくりではありますが、以上のような方法でiPhoneの動きをMacの3Dモデルに反映する事ができました。

iPhone Acc Demo from HR2 on Vimeo.



ただ、このままでは、値を取りこぼした時に、モデルが消えたり、ガクガクした動きになってしまうので、スムージングをかけるなど工夫が必要です。別件で作ったサンプルでは、その辺いろいろ工夫してみました。サウンドやiPhoneのタッチも使っています。

iPhone Acc Demo 2 from HR2 on Vimeo.



最後に今回のコードです。
testApp.h

#ifndef _TEST_APP
#define _TEST_APP

#include "ofMain.h"
#include "ofx3DModelLoader.h"
#include "ofxNetwork.h"

class testApp : public ofBaseApp{

public:
void setup();
void update();
void draw();

void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);

ofx3DModelLoader modelObj;
ofxTCPServer TCP;
};
#endif

testApp.cpp

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){

// 基本設定 --------------------------
ofBackground(0, 0, 0);
ofSetFrameRate(60);
ofEnableSmoothing();
ofEnableSmoothing();
ofSetFullscreen(true);

// 隠面消去 --------------------------
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

// 照明 -----------------------------
GLfloat lt0_position[] = { 100, 100, -200, 0 };
GLfloat lt0_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat lt0_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lt0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, lt0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lt0_diffuse);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

// モデルデータロード -----------------------------
modelObj.loadModel("modelSample.3ds", 20 );

// TCP のセットアップ -----------------------------
TCP.setup(11999);
}
//--------------------------------------------------------------
void testApp::update(){
}
//--------------------------------------------------------------
void testApp::draw(){
ofPoint data = 0.0;
for(int i = 0; i < TCP.getNumClients(); i++){
// クライアントから送られている文字列の受信
string str = TCP.receive(i);

if (str.length() > 0) {
// カンマ区切りで分割。Floatに変換して格納。
vector <string> dataStr = ofSplitString( str, "," );
data.x = ofToFloat( dataStr[0] );
data.y = ofToFloat( dataStr[1] );
data.z = ofToFloat( dataStr[2] );

// 角度に変換
ofPoint rotation = 0.0;
rotation.x = asin(data.y) * ( 180.0/PI );
rotation.y = 0.0;
rotation.z = asin(data.x) * ( 180.0/PI );

// オブジェクトに回転をセット
glPushMatrix();
glTranslatef(ofGetWidth()/2.0, ofGetHeight()/2,0);
modelObj.setRotation( 0, rotation.x, 1, 0, 0 );
modelObj.setRotation( 1, rotation.y, 0, 1, 0 );
modelObj.setRotation( 2, rotation.z, 0, 0, 1 );
modelObj.draw();
glPopMatrix();
}
}
}