#topicpath

** 惑星上の落下運動をARで表現する [#z4a02a3a]
[[Processing>../]] と NyARToolkit を用いて、惑星上で物体を落下させたときの様子を表現するプログラムの作成
*** 最新版 [#f5344561]
- 環境
-- Processing 2.2.1(Windows 32bit版)>https://processing.org/download/]]
-- [[NyARToolkit 2.1.0>https://github.com/nyatla/NyARToolkit-for-Processing/releases]]
-- マーカー [[Utah大学>http://www.cs.utah.edu/gdc/projects/augmentedreality/download.html]]
~
~
- 準備・実行手順
++ Processing, NyARToolkit, カメラが使える環境を整える。
++ Processing を開いた上で、次項のプログラムを張り付けて保存する。
++ マーカーのデータをダウンロードし、上記のプログラムが保存されているフォルダ内に、data フォルダを作成し、*.patt ファイルを保存する。
++ マーカーを印刷する。
++ プログラムを実行し、カメラにマーカーを向けてみる。
~
~
- プログラム~
適当に作っているので、問題もあると思う。
 //
 //  地球、月、金星、火星、木星上での重力による運動
 //  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();
     }
   }
 }

*** 古い版 [#zdcdddcb]
- 環境
-- Processing 1.5.1
-- NyARToolkit 1.1.6
-- GSVideo 1.0
-- マーカー [[Utah大学>http://www.cs.utah.edu/gdc/projects/augmentedreality/download.html]]
~
- プログラミング~
  このビデオは、[[Make のブログ>http://jp.makezine.com/blog/2012/02/how-to-augmented-reality-with-processing.html]] と、そこで紹介されている[[記事>http://www.creativeapplications.net/processing/augmented-reality-with-processing-tutorial-processing/]] を参考に(というより、ほとんどぱくって)、次のようなプログラムを作って作成しました。~
現在の Processing 2.2.1, NyARToolkit for Processing 2.1.0 では動きません!
 //
 //  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);
 }


トップ   新規 検索 最終更新   ヘルプ   最終更新のRSS