Processing と NyARToolkit を用いて、惑星上で物体を落下させたときの様子を表現するプログラムの作成
// // 地球、月、金星、火星、木星上での重力による運動 // Gravitational freefall motion on the Earth, Moon, Mars, Venus, and Jupiter // // 桜美林大学 森 // 2015-09-16 // import jp.nyatla.nyar4psg.*; // the NyARToolkit Processing library import processing.video.*; // the video library public MultiMarker nya; // Preparation for Markers ----------------------------------------------------------------------------------------------------- int numMarkers = 10; // 利用する AR マーカーの数 / Number of Markers String[] patterns = {"4x4_01.patt", "4x4_02.patt", "4x4_03.patt", "4x4_04.patt", "4x4_05.patt", // マーカーのパターンファイル / Marker's pattern files "4x4_06.patt", "4x4_07.patt", "4x4_08.patt", "4x4_09.patt", "4x4_10.patt"}; // スケッチの data フォルダに / must be in data folder float markersize = 136; // 印刷されたマーカーのサイズ(mm) / size of markers in mm. // Preparation for Camera ------------------------------------------------------------------------------------------------------ String camPara = "camera_para.dat"; // カメラのパラメタ / Camera's parameter int arWidth = 640; // Windows の場合には Processing の制限で 640x480 / Size must be 640x480. int arHeight = 480; Capture cam; // Physical Conatants ---------------------------------------------------------------------------------------------------------- public final float V0 = 2.0; // Initial velocity (Throwing) public final float V2 = sqrt(V0); // 重力加速度 / Gravitational Acceleration ( in mm/ms^2 ) public final float GE = 9.807e-3; // 地球 / Earth public final float GM = 1.622e-3; // 月 / Moon public final float GV = 8.870e-3; // 金星 / Venus public final float GA = 7.710e-3; // 火星 / Mars public final float GJ = 23.120e-3; // 木星 / Jupiter // | 地 月 金 火 木| 地 月 金 火 木| public final int[] inittime = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; public final float[] vx = { 0, 0, 0, 0, 0, V2, V2, V2, V2, V2}; // 初速 x成分 単位 mm/ms / Initial velocity in x public final float[] vy = { 0, 0, 0, 0, 0, V2, V2, V2, V2, V2}; // 初速 y成分 単位 mm/ms / Initial velocity in y public final float[] gr = { GE, GM, GV, GA, GJ, GE, GM, GV, GA, GJ}; // 重力加速度 単位 mm/ms^2 / Gravitational Acceleration public final String[] plid = {"Earth Fall", "Moon Fall", "Venus Fall", "Mars Fall", "Jupiter Fall", "Earth Throw","Moon Throw","Venus Throw","Mars Throw","Jupiter Throw"}; public final int BS = 10; // ボールのサイズ / Ball size // ----------------------------------------------------------------------------------------------------------------------------- void setup() { // カメラの準備 / Camera Initialization size(arWidth, arHeight, OPENGL); cam = new Capture(this, arWidth, arHeight); cam.start(); // キャプチャ開始 / start capture noStroke(); // 図形の枠なし / no frames // マーカー準備 / Initialization for AR nya = new MultiMarker(this, arWidth, arHeight, camPara, NyAR4PsgConfig.CONFIG_DEFAULT); // コンストラクタ nya.setLostDelay(1); // 指定回数以上連続して認識できなかったとき、認識に失敗となる。1 → すぐに失敗。 for (int i=0; i<numMarkers; i++) { nya.addARMarker(patterns[i], markersize); // マーカーを追加。第二引数はマーカーのサイズ(mm) } } // ----------------------------------------------------------------------------------------------------------------------------- void draw() { if( cam.available() ) { // カメラが動いているときだけ / only in case of successful capturing cam.read(); // 読み込み / reading nya.drawBackground(cam); // frustumを考慮した背景描画 / place video picture on the background nya.detect(cam.get()); // マーカーの認識 / detect markers drawBalls(); // ボールの描出 / draw balls } } // ----------------------------------------------------------------------------------------------------------------------------- void drawBalls() { int etime = 0; // 経過時間 / Elapsed Time float posx, posy; // ボールの位置 / Ball's coordinates nya.setARPerspective(); // Projection Matrix をカメラのものにする…そうだ。 lights(); // 適当な陰影をつけてくる。これをコメントアウトすると、のっぺりになる。 for (int i=0; i<numMarkers; i++) { // マーカーの数だけ繰り返し調べる / loop for markers if ((!nya.isExistMarker(i))) { // マーカー見失い → 時間をリセットし、次へ inittime[i] = -1; continue; } //-------------------------- 以下はマーカーが見つかったら実行 setMatrix(nya.getMarkerMatrix(i)); // nya.getMarkerMatrix(i) : 変換行列を取得 fill(255); rect(-markersize/2, -markersize/2, markersize, markersize); fill( 0); textSize(10); rotateX(PI); text(plid[i], -markersize/2 ,80); rotateX(-PI); if( vx[i] == 0 ){ translate( 0, markersize/2) ; // 上端を原点に変更する(元々原点は面の中心) }else{ translate( -markersize/2, -markersize/2) ; // 左下を原点に変更する(元々原点は面の中心) } etime = millis() - inittime[i]; // 経過時間 ただし、最初の 1000ms はゼロにし、止めておく。 if( etime < 1000 ){ etime = 0; }else{ etime -= 1000; } if ( inittime[i] == -1 ){ inittime[i] = millis(); }// 個々の初期時間をセットする。 posx = vx[i] * etime; // 投射運動の式 posy = vy[i] * etime - gr[i] / 2 * etime * etime; fill(200,200,255); // 球の描出 translate( posx, posy, BS); sphere(BS); translate(-posx, -posy, -BS); if ( posx > 5e3 || posy > 5e3 || etime > 3000 ){ // 時間が経過したら or 画面から明らかに外れたら、初期化 inittime[i] = millis(); } } }
// // Freefall motion due to the Gravity on the Earth, on the Moon, and on the Mars. // // Based on the following program // Augmented Reality Dynamic Example by Amnon Owed (21/12/11) // Processing 1.5.1 + NyARToolkit 1.1.6 + GSVideo 1.0 import java.io.*; // for the loadPatternFilenames() function import processing.opengl.*; // for OPENGL rendering import jp.nyatla.nyar4psg.*; // the NyARToolkit Processing library import codeanticode.gsvideo.*; // the GSVideo library String camPara = "D:/My Documents/Processing/libraries/NyAR4psg/data/camera_para.dat"; // カメラのパラメタ? String patternPath = "D:/デスクトップ/開発工作/Processing/patternMaker/examples/ARToolKit_Patterns"; // AR マーカーを学習させたパターンファイルへのパス。 // Preparation for Camera ------------------------------------------------------------------------------------------------------ int arWidth = 640; // カメラから修得する画像のサイズ。カメラに依存する。大きすぎると遅くなる。 int arHeight =360; GSCapture cam; // Preparation for AR --------------------------------------------------------------------------------------------------------- int numMarkers = 10; // 利用する AR マーカーの数 float markersize = 136; int[] inittime = new int[numMarkers]; float[] vx = new float[numMarkers]; // 初速x成分 単位 mm/ms float[] vy = new float[numMarkers]; // 初速y成分 単位 mm/ms float[] gr = new float[numMarkers]; // 重力加速度 単位 mm/ms^2 MKS の 1/1000 MultiMarker nya; void setup() { // Initialization for Camera ------------------------------------------------------------------------------------------------- size(arWidth, arHeight, OPENGL); cam = new GSCapture(this, arWidth, arHeight); cam.start(); // start capturing noStroke(); // turn off stroke for the rest of this sketch :-) // Initialization for AR ------------------------------------------------------------------------------------------------- // create a new MultiMarker at a specific resolution (arWidth x arHeight), with the default camera calibration and coordinate system nya = new MultiMarker(this, arWidth, arHeight, camPara, NyAR4PsgConfig.CONFIG_DEFAULT); // set the delay after which a lost marker is no longer displayed. by default set to something higher, but here manually set to immediate. nya.setLostDelay(1); String[] patterns = loadPatternFilenames(patternPath); // Initialization for Individual Markers ------------------------------------------------------------------------------------- // for the selected number of markers, add the marker for detection // create an individual scale, noiseScale and maximum mountainHeight for that marker (= mountain) for (int i=0; i<numMarkers; i++) { nya.addARMarker(patternPath + "/" + patterns[i], markersize); // リファレンスマニュアルと違う?第二引数は、ミリメートル単位でのマーカーのサイズのようだ。 // // マーカーごとに、それぞれ別々の運動を表現したい場合には、ここを変更する。 // inittime[i] = -1; vx[i] = 1.4142; vy[i] = 1.4142; gr[i] = 9.8e-3 * i / (numMarkers - 1); } gr[8] = 1.622e-3; // 月 gr[7] = 8.87e-3; // 金星 gr[6] = 3.71e-3; // 火星 gr[5] = 23.12e-3; // 木星 } void draw() { // if there is a cam image coming in... if (cam.available()) { cam.read(); // read the cam image background(0); // a background call is needed for correct display of the marker results image(cam, 0, 0, width, height); // 表示 : display the image at the width and height of the sketch window // create a copy of the cam image at the resolution of the AR detection (otherwise nya.detect will throw an assertion error!) PImage cSmall = cam.get(); cSmall.resize(arWidth, arHeight); nya.detect(cSmall); // detect markers in the image drawBalls(); // draw dynamically flowing mountains on the detected markers (3D) } } void drawBalls() { int etime = 0; float posx, posy; nya.setARPerspective(); // Projection Matrix をカメラのものにする……そうだ。 lights(); // 適当な陰影をつけてくる。これをコメントアウトすると、のっぺりになる。 for (int i=0; i<numMarkers; i++) { // マーカーの数だけ繰り返し調べる // if the marker does NOT exist (the ! exlamation mark negates it)... if ((!nya.isExistMarker(i))) { // マーカーが見つけられなかったら時間をリセット inittime[i] = -1; continue; } // マーカーが見つかったら以下を実行 setMatrix(nya.getMarkerMatrix(i)); // nya.getMarkerMatrix(i) : 変換行列を取得 translate( -markersize/2, -markersize/2) ; // 座標(-resX/2, -resY/2)を原点に変更する → ARのオブジェクトは全部真中にくる。 // マーカーを塗りつぶす fill(180); beginShape(); vertex(0, 0); vertex(0, markersize); vertex(markersize, markersize); vertex(markersize, 0); endShape(CLOSE); // ボールを描く etime = millis() - inittime[i]; if( etime < 1000 ){ etime = 0; }else{ etime -= 1000; } if ( inittime[i] == -1 ){ inittime[i] = millis(); } posx = vx[i] * etime; posy = vy[i] * etime - gr[i] / 2 * etime * etime; // println( etime); fill(200,200,255); translate( posx, posy); sphere(10); translate(-posx, -posy); // 時間が経過したら、また、画面から明らかに外れたら、初期化する if ( posx > 3e3 || posy > 3e3 || etime > 3000 ){ inittime[i] = millis(); } } // reset to the default perspective perspective(); } // this function loads .patt filenames into a list of Strings based on a full path to a directory (relies on java.io) String[] loadPatternFilenames(String path) { File folder = new File(path); FilenameFilter pattFilter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".patt"); } }; return folder.list(pattFilter); }