NyARToolKit

NyARToolKit for Android

Section 14 AR描画部分のソースコード説明

サンプルソースのAR描画(ARToolkitDrawer.java)解説を行っていきます。

暫定版

この記事は暫定版です。順次更新されます。
この表示が消えるまで突っ込み禁止。

コンストラクタ(初期化)

カメラ出力、マーカーサイズ、マーカーパターン、表示格納領域を指定します。

/**
 * 初期化処理
 * マーカーパターン、カメラパラメータはここで読み込む
 */

private void initialization(InputStream camePara, int[] width, ArrayList<InputStream> patt) {
	mNumPatt = patt.size();
	marker_width = new double[mNumPatt];
	ar_code = new NyARCode[mNumPatt];
	try {
		for (int i = 0; i < mNumPatt; i++) {
			// マーカーの幅
			marker_width[i] = width[i];

			// マーカーの分割数
			ar_code[i] = new NyARCode(16, 16);
			ar_code[i].loadARPatt(patt.get(i));
		}

		ar_param = new NyARParam();
		ar_param.loadARParam(camePara);
	} catch (Exception e) {
		Log.e("nyar", "resource loading failed", e);
	}
}

NyARCodeはARToolKitのマーカーパターン1個のデータを格納します。 引数は作成するマーカパターンの横解像度,作成するマーカパターンの縦解像度です。

decodeYUV420SP(YUV→RGB)

カメラ画像はYUVフォーマットで取得されるため、RGB形式に変換してからARの認識処理に渡しています。
ここでは「jni」の方で処理されているため、詳細はjni.yuv420sp2rgb.yuv420sp2rgb.cを参照してください。

draw:メイン描画処理

//ARメイン処理
public void draw(byte[] data) {

	if(data == null) {
		Log.d("AR draw", "data= null");
		return;
	}
	Log.d("AR draw", "data.length= " + data.length);
	//スクリーンサイズ指定
	int width = 320;
	int height = 240;

	// RGB格納用
	byte[] buf = new byte[width * height * 3];

	// assume YUV420SP
	long time1 = SystemClock.uptimeMillis();
	//YUV420からRGB24変換
	decodeYUV420SP(buf, data, width, height, 1);
	long time2 = SystemClock.uptimeMillis();
	Log.d("ARToolkitDrawer", "RGB decode time: " + (time2 - time1) + "ms");

	float[][] resultf = new float[MARKER_MAX][16];

	int found_markers;
	int ar_code_index[] = new int[MARKER_MAX];
	//NyARToolKitの初期化 - カメラパラメータの読み込み
	createNyARTool(width, height);
	
	// マーカー検出
	try {
		Log.d("AR draw", "Marker detection.");
		raster = new NyARRgbRaster_RGB(width, height);
		raster.wrapBuffer(buf);
		found_markers = nya.detectMarkerLite(raster, 100);
	} catch (NyARException e) {
		Log.e("AR draw", "marker detection failed", e);
		return;
	}

	boolean isDetect = false;

	// マーカーが検出された場合、描画
	if (found_markers > 0) {
		Log.d("AR draw", "!!!!!!!!!!!exist marker." + found_markers + "!!!!!!!!!!!");
		// プロジェクションをGL用に変換
		float[] cameraRHf = new float[16];
		toCameraFrustumRHf(ar_param, cameraRHf);

		if (found_markers > MARKER_MAX)
			found_markers = MARKER_MAX;
		for (int i = 0; i < found_markers; i++) {
			//マーカーの一致率で 60% より小さい場合は認識していないと半定する。一致率は 0.0 < n < 1.0 の間
			if (nya.getConfidence(i) < 0.60f)
				continue;
			try {
				ar_code_index[i] = nya.getARCodeIndex(i);
				NyARTransMatResult transmat_result = ar_transmat_result;
				nya.getTransmationMatrix(i, transmat_result);
				//OpenGLのModelView行列へ変換
				toCameraViewRHf(transmat_result, resultf[i]);
				isDetect = true;
			} catch (NyARException e) {
				Log.e("AR draw", "getCameraViewRH failed", e);
				return;
			}
		}
		//検出したマーカーの上に3Dモデル再描画
		mRenderer.objectPointChanged(found_markers, ar_code_index, resultf, cameraRHf);
	} else {
		Log.d("AR draw", "not exist marker.");

		mRenderer.objectClear();
	}
	// モデルデータなどに音をつける場合に使用
	if (isDetect) {
		if (mMediaPlayer != null) {
			if (!mMediaPlayer.isPlaying())
				mMediaPlayer.start();
		}
	}
	else {
		if (mMediaPlayer != null) {
			if (mMediaPlayer.isPlaying())
				mMediaPlayer.pause();
		}
	}
}

drawではマーカーの認識、描画等を行っています。
まずカメラ画像をYUV420→RGB24に変換を行い、変換後の画像をARToolkitに渡します。
ARToolkitに渡された画像からマーカーを認識し、マーカーの座標を取得します。 マーカーの座標に3Dモデルを出力するように再描画をかけ表示を行っています。

とても簡単なソースコード解説はこれで終了になります。