- 追加された行はこの色です。
- 削除された行はこの色です。
#topicpath
** 惑星上の落下運動をARで表現する [#z4a02a3a]
[[Processing>../]] と NyARToolkit を用いて、惑星上で物体を落下させたときの様子を表現するプログラムの作成
*** 最新版 [#f5344561]
*** 配布物と説明 [#nc8f67e7]
*** 開発(最新版) [#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-18 : パターンファイルを専用に作った。
// 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;
public Capture cam;
Capture cam;
// Preparation for Markers -----------------------------------------------------------------------------------------------------
int numMarkers = 10; // 利用する AR マーカーの数 / Number of Markers
float markersize = 80; // 印刷されたマーカーのサイズ(mm) / size of markers in mm.
String[] patterns = {"EF.pat", "MF.pat", "VF.pat", "AF.pat", "JF.pat", // マーカーのパターンファイル / Marker's pattern files
"ET.pat", "MT.pat", "VT.pat", "AT.pat", "JT.pat"}; // スケッチの data フォルダに / must be in data folder
// 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);
fill(180); rect(-markersize/2, -markersize/2, markersize, markersize);
fill( 0); textSize(10); rotateX(PI); text(plid[i], -markersize/2 ,50); 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;
lights(); // 適当な陰影をつけてくる。これをコメントアウトすると、のっぺりになる。
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]
*** 開発(古い版) [#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/]] を参考に(というより、ほとんどぱくって)、次のようなプログラムを作って作成しました。~
- プログラム~
[[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/]] を参考にした(というより、ほとんどぱくった)
プログラムです。(&ref(OldProgram_for_FallingOnPlanets.pde);)~
現在の 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);
}