/*
* PROJECT: NyARToolkit for Android SDK
* --------------------------------------------------------------------------------
* This work is based on the original ARToolKit developed by
* Hirokazu Kato
* Mark Billinghurst
* HITLab, University of Washington, Seattle
* http://www.hitl.washington.edu/artoolkit/
*
* NyARToolkit for Android SDK
* Copyright (C)2010 NyARToolkit for Android team
* Copyright (C)2010 R.Iizuka(nyatla)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For further information please contact.
* http://sourceforge.jp/projects/nyartoolkit-and/
*
* This work is based on the NyARToolKit developed by
* R.Iizuka (nyatla)
* http://nyatla.jp/nyatoolkit/
*
* contributor(s)
* Atsuo Igarashi
*/
package jp.androidgroup.nyartoolkit;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.os.SystemClock;
import android.util.Log;
import java.io.InputStream;
import java.util.ArrayList;
//import min3d.core.Renderer;
import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.core.NyARCode;
import jp.nyatla.nyartoolkit.core.param.NyARParam;
import jp.nyatla.nyartoolkit.core.raster.rgb.NyARRgbRaster_RGB;
import jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult;
import jp.nyatla.nyartoolkit.core.types.NyARBufferType;
import jp.nyatla.nyartoolkit.core.types.matrix.NyARDoubleMatrix44;
import jp.nyatla.nyartoolkit.detector.NyARDetectMarker;
import jp.nyatla.nyartoolkit.jogl.utils.NyARGLUtil;
/**
* ARToolKit Drawer
* マーカー認識部分などが含まれたクラス
*/
public class ARToolkitDrawer
{
/**
* マーカーのパターン数
*/
private int mNumPatt;
/**
* 一回の処理で検出できる最大のマーカー数。誤認識分も含まれるので少なすぎても駄目、多すぎると処理負荷増
*/
private static final int MARKER_MAX = 8;
/**
* @see jp.nyatla.nyartoolkit.detector.NyARDetectMarker
*/
private NyARDetectMarker nya = null;
/**
* @see jp.nyatla.nyartoolkit.core.raster.rgb.NyARRgbRaster_RGB
*/
private NyARRgbRaster_RGB raster = null;
/**
* カメラパラメータを保持するクラス
* @see jp.nyatla.nyartoolkit.core.param.NyARParam
*/
private NyARParam ar_param = null;
/**
* マーカーのパターン情報を管理するクラス
* @see jp.nyatla.nyartoolkit.core.param.NyARParam
*/
private NyARCode[] ar_code;
/**
* マーカーの幅
*/
private double marker_width[];
/**
* 検出したマーカーの座標変換行列
* @see jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult
*/
private NyARTransMatResult ar_transmat_result = new NyARTransMatResult();
// Renderer for metasequoia model
private ModelRenderer mRenderer = null;
// Renderer of min3d
// private Renderer mRenderer;
private MediaPlayer mMediaPlayer = null;
static {
System.loadLibrary("yuv420sp2rgb");
}
public static native void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height, int type);
public static native void decodeYUV420SP(byte[] rgb, byte[] yuv420sp, int width, int height, int type);
/**
* Constructor
*
* @param camePara
* @param patt
* @param mRenderer
* @param mTranslucentBackground
* @param isYuv420spPreviewFormat
*/
// Renderer for metasequoia model
public ARToolkitDrawer(InputStream camePara, int[] width, ArrayList<InputStream> patt, ModelRenderer mRenderer) {
// Renderer of min3d
// public ARToolkitDrawer(InputStream camePara, int[] width, ArrayList<InputStream> patt, Renderer mRenderer) {
this.mRenderer = mRenderer;
this.initialization(camePara, width, patt);
}
/**
* 初期化処理
* マーカーパターン、カメラパラメータはここで読み込む
*/
private void initialization(InputStream camePara, int[] width, ArrayList<InputStream> patt) {
mNumPatt = patt.size();
//System.out.println("マーカーサイズ " + 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);
}
}
/**
* NyARToolKitの初期化
* カメラパラメータの読み込み
*
* @param w スクリーンサイズ(width)
* @param h スクリーンサイズ(height)
*/
private void createNyARTool(int w, int h) {
// NyARToolkit setting.
try {
if (nya == null) {
ar_param.changeScreenSize(w, h);
// マーカーの枠線幅を変えることは可能。
// NyARDetectMarker 内にコメントを追加したのでその部分を参照のこと
nya = new NyARDetectMarker(ar_param, ar_code, marker_width, mNumPatt, NyARBufferType.BYTE1D_B8G8R8_24);
nya.setContinueMode(true);
//System.out.println("マーカー情報 " + nya);
}
Log.d("nyar", "resources have been loaded");
} catch (Exception e) {
Log.e("nyar", "resource loading failed", e);
}
}
/**
*
* @param mediaplayer
*/
public void setMediaPlayer(MediaPlayer mediaplayer) {
this.mMediaPlayer = mediaplayer;
}
/**
* NyARGLUtil.toCameraFrustumRH()の出力double[]をfloat[]に変換する
* @param i_arparam
* @param o_gl_projection
*/
public static void toCameraFrustumRHf(NyARParam i_arparam, float[] o_gl_projection)
{
double[] mf = new double[16];
NyARGLUtil.toCameraFrustumRH(i_arparam, NyARGLUtil.SCALE_FACTOR_toCameraFrustumRH_NYAR2, 10, 10000, mf);
for (int i = 0; i < mf.length; i++) {
o_gl_projection[i] = (float) mf[i];
}
}
/**
* NyARGLUtil.toCameraViewRH()の出力double[]をfloat[]に変換する
* @param i_ny_result
* @param o_gl_result
*/
public static void toCameraViewRHf(NyARDoubleMatrix44 i_ny_result, float[] o_gl_result)
{
double[] mf = new double[16];
NyARGLUtil.toCameraViewRH(i_ny_result, NyARGLUtil.SCALE_FACTOR_toCameraViewRH_NYAR2, mf);
for (int i = 0; i < mf.length; i++) {
o_gl_result[i] = (float) mf[i];
}
}
/**
* 描画処理部分
* メインループ処理と読み替えても良い
* @param data
*/
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;
// start coordinates calculation.
byte[] buf = new byte[width * height * 3];
// assume YUV420SP
long time1 = SystemClock.uptimeMillis();
// convert YUV420SP to 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];
createNyARTool(width, height);
// Marker detection
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;
// An OpenGL object will be drawn if matched.
if (found_markers > 0) {
Log.d("AR draw", "!!!!!!!!!!!exist marker." + found_markers + "!!!!!!!!!!!");
// Projection transformation.
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++) {
if (nya.getConfidence(i) < 0.50f)
continue;
try {
ar_code_index[i] = nya.getARCodeIndex(i);
NyARTransMatResult transmat_result = ar_transmat_result;
//マーカーの一致度取得
nya.getTransmationMatrix(i, transmat_result);
toCameraViewRHf(transmat_result, resultf[i]);
isDetect = true;
} catch (NyARException e) {
Log.e("AR draw", "getCameraViewRH failed", e);
return;
}
}
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();
}
}
}
}