公開日:2009/11/1 0:00:00

NyARToolKit for Java

Section 12 ソースコード解説 AR部分

Captureクラスの修正

カメラパラメータのファイルを読み込ませる処理を入れます。

まずは、カメラパラメータファイルをクラス変数として定義。

	private static final int SCREEN_Y = 480;

	/**
	 * カメラパラメータファイルの定義
	 */
	private String PARAM_FILE = "./Data/camera_para.dat";

次に、そのファイルを読み込ませる処理を入れます。

	/**
	 * 初期化処理
	 */
	private void _init() {
		//キャプチャの準備
		try {
			/*
			 * 複数のキャプチャデバイスがあって切り替えとかやる場合はこの辺りを工夫するべし
			 */
			JmfCaptureDeviceList devlist = new JmfCaptureDeviceList();
			_captureDev = devlist.getDevice(0);
			_captureDev.setCaptureFormat(SCREEN_X, SCREEN_Y, 20f);
			
			//NyARToolkitの準備
			_nyARParam = new NyARParam();
			_nyARParam.loadARParamFromFile(PARAM_FILE);
			_nyARParam.changeScreenSize(SCREEN_X, SCREEN_Y);

汎用化する場合は、この部分を工夫する必要があります。
この前の段階でカメラデバイスの情報を取得しているので、それを用いてカメラ毎にパラメータファイルを切り替えたり……
もっとも、その情報を集めるのが大変ですが。

表示するオブジェクト

付属しているサンプルでは同じファイル内に書かれていたのですが、切り替えとかやりたくなりそうなので、別ファイルにしてみます。

これまでと同様の方法でクラスを使いします。
具体的には、Packageは「jp.sixwish.NyARToolKit.Sample」、Nameは「Cube」。
Superclass、Interfacesは空欄のまま、チェックボックスは「Generate comments」だけつけます。

/**
 * 
 */
package jp.sixwish.NyARToolKit.Sample;

/**
 * @author F.Rokubou
 *
 */
public class Cube {

}

生成されたコードを修正

/**
 * Sixwish.jp 実験用サンプルパッケージ
 * 
 * @copyright (C) 2009 The Sixwish project
 * @license http://sixwish.jp/licenses/nyartkgpl The GPL License
 */
package jp.sixwish.NyARToolKit.Sample;

/**
 * @see javax.media.opengl.GL
 */
import javax.media.opengl.GL;

/**
 * @author F.Rokubou
 */
public class Cube {
	public void drawCube(GL _gl) {
		int polyList = 0;
		//マーカーサイズに対して0.5倍なので、4cmの立方体
		float fSize = 0.5f;
		int f, i;
		float[][] cube_vertices = new float[][] {
				{ 1.0f,  1.0f,  1.0f },
				{ 1.0f, -1.0f,  1.0f },
				{-1.0f, -1.0f,  1.0f },
				{-1.0f,  1.0f,  1.0f },
				{ 1.0f,  1.0f, -1.0f },
				{ 1.0f, -1.0f, -1.0f },
				{-1.0f, -1.0f, -1.0f },
				{-1.0f,  1.0f, -1.0f } };
		float[][] cube_vertex_colors = new float[][] {
				{ 1.0f, 1.0f, 1.0f },
				{ 1.0f, 1.0f, 0.0f },
				{ 0.0f, 1.0f, 0.0f },
				{ 0.0f, 1.0f, 1.0f },
				{ 1.0f, 0.0f, 1.0f },
				{ 1.0f, 0.0f, 0.0f },
				{ 0.0f, 0.0f, 0.0f },
				{ 0.0f, 0.0f, 1.0f } };
		int cube_num_faces = 6;
		short[][] cube_faces = new short[][] {
				{ 3, 2, 1, 0 },
				{ 2, 3, 7, 6 },
				{ 0, 1, 5, 4 },
				{ 3, 0, 4, 7 },
				{ 1, 2, 6, 5 },
				{ 4, 5, 6, 7 } };

		if (polyList == 0) {
			polyList = _gl.glGenLists(1);
			_gl.glNewList(polyList, GL.GL_COMPILE);
			_gl.glBegin(GL.GL_QUADS);
			for (f = 0; f < cube_num_faces; f++)
				for (i = 0; i < 4; i++) {
					_gl.glColor3f(cube_vertex_colors[cube_faces[f][i]][0], cube_vertex_colors[cube_faces[f][i]][1], cube_vertex_colors[cube_faces[f][i]][2]);
					_gl.glVertex3f(cube_vertices[cube_faces[f][i]][0] * fSize, cube_vertices[cube_faces[f][i]][1] * fSize, cube_vertices[cube_faces[f][i]][2] * fSize);
				}
			_gl.glEnd();
			_gl.glColor3f(0.0f, 0.0f, 0.0f);
			for (f = 0; f < cube_num_faces; f++) {
				_gl.glBegin(GL.GL_LINE_LOOP);
				for (i = 0; i < 4; i++)
					_gl.glVertex3f(cube_vertices[cube_faces[f][i]][0] * fSize, cube_vertices[cube_faces[f][i]][1] * fSize, cube_vertices[cube_faces[f][i]][2] * fSize);
				_gl.glEnd();
			}
			_gl.glEndList();
		}

		_gl.glPushMatrix(); // Save world coordinate system.
		_gl.glTranslatef(0.0f, 0.0f, 0.5f); // Place base of cube on marker surface.
		_gl.glRotatef(0.0f, 0.0f, 0.0f, 1.0f); // Rotate about z axis.
		_gl.glDisable(GL.GL_LIGHTING); // Just use colors.
		_gl.glCallList(polyList); // Draw the cube.
		_gl.glPopMatrix(); // Restore world coordinate system.
	}
}

解説していると長いのでパス。

EventListnerの修正

編集を始める前に、このファイルのバックアップを取っておくと良いかも……やり方はお任せしますが。

本題。 修正箇所が多岐にわたるので確認しながら進めてください。

まずは必要なクラスをインポート。

/**
 * @see jp.nyatla.nyartoolkit.core.NyARCode
 * @see jp.nyatla.nyartoolkit.core.param.NyARParam
 * @see jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult
 * @see jp.nyatla.nyartoolkit.detector.NyARDetectMarker
 * @see jp.nyatla.nyartoolkit.jogl.utils.GLNyARRaster_RGB
 * @see jp.nyatla.nyartoolkit.jogl.utils.NyARGLUtil
 */
import jp.nyatla.nyartoolkit.core.NyARCode;
import jp.nyatla.nyartoolkit.core.param.NyARParam;
import jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult;
import jp.nyatla.nyartoolkit.detector.NyARDetectMarker;
import jp.nyatla.nyartoolkit.jogl.utils.GLNyARRaster_RGB;
import jp.nyatla.nyartoolkit.jogl.utils.NyARGLUtil;

クラス変数の定義を追加

	private NyARGLUtil _nyARGLUtil = null;
	
	/**
	 * @see jp.nyatla.nyartoolkit.core.param.NyARParam
	 */
	private NyARParam _nyARParam = null;
	
	/**
	 * @see jp.nyatla.nyartoolkit.detector.NyARSingleDetectMarker
	 */
	private NyARSingleDetectMarker _nyARDetectMarker = null;
	
	/**
	 * @see jp.nyatla.nyartoolkit.core.NyARCode
	 */
	private NyARCode _arCodes = null;
	
	/**マーカーの一辺の長さ
	 * 
	 */
	private double width = null;
	
	/**
	 * 
	 */
	private double[] _camera_projection = new double[16];
	
	/**
	 */
	private final String MARKER_PATT_FILE = "./Data/patt.hiro";
	
	/**
	 * 
	 */
	private double[] __display_wk = new double[16];

	/**
	 * @see jp.sixwish.NyARToolKit.Sample.util.Capture
	 */
	private Capture _caputure = null;

	/**
	 * 表示するオブジェクト
	 */
	private Cube cubeObject = new Cube();
	
	/**
	 * @see jp.nyatla.nyartoolkit.core.transmat.NyARTransMat
	 */
	private NyARTransMatResult __display_transmat_result = new NyARTransMatResult();

displayメソッドの修正。ここが重要な部分。

	/**
	 * キャプチャ画像の出力と3Dオブジェクトの合成を行う。
	 * Animatorクラスによって、繰り返し呼び出されるメソッドです。
	 *
	 * @param drawable
	 */
	@Override
	public void display(GLAutoDrawable drawable)
	{
		//
		NyARTransMatResult transmatResult = __display_transmat_result;
		
		try {
			if (!_nyARRaster.hasData()) {
				return;
			}
			_gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Clear the buffers for new frame.
			// 画像チェックして背景を書く
			boolean foundMarkers = false;
			synchronized (_nyARRaster) {
				// マーカーの検出したかを確認
				foundMarkers = _nyARDetectMarker.detectMarkerLite(_nyARRaster, 100);
				//背景を書く
				_nyARGLUtil.drawBackGround(_nyARRaster, 1.0);
			}
			// 検出したマーカーを検査
			if (foundMarkers) {
				// Projection transformation
				_gl.glMatrixMode(GL.GL_PROJECTION);
				_gl.glLoadMatrixd(_camera_projection, 0);
				_gl.glMatrixMode(GL.GL_MODELVIEW);
				// Viewing transformation
				_gl.glLoadIdentity();
				//変換行列を取得
				_nyARDetectMarker.getTransmationMatrix(0, transmatResult);
				//変換行列をOpenGL形式に変換
				_nyARGLUtil.toCameraViewRH(transmatResult, __display_wk);
				_gl.glLoadMatrixd(__display_wk, 0);

				// All other lighting and geometry goes here.
				this.cubeObject.drawCube(_gl);
			}
			
			Thread.sleep(1);//タスク実行権限を一旦渡す
		} catch (Exception e) {
			e.printStackTrace();
		}
		return;
	}

無駄にマルチマーカーに対応してあるのでこんな書き方。 「ひとつでいい」という場合は、NyARSingleDetectMarkerを使う。

続いて初期化処理。ここでマーカーを登録している。

	/**
	 * 初期化処理を行う
	 * キャプチャ画像描写用クラスの生成と、合成3Dオブジェクトプロパティの取得、設定を行います。
	 *
	 * @param drawable
	 */
	public void init(GLAutoDrawable drawable) {
		// GLオブジェクトを取得する
		_gl = drawable.getGL();
		_gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		//NyARToolkitの準備
		try {
			width = new double[] { 80.0 };
			// ARCode(マーカー)の初期化
			_arCodes = new NyARCode(16, 16);
			_arCodes.loadARPattFromFile(MARKER_PATT_FILE);
			
			/* 
			 * 初期化されたマーカーをマーカー識別クラスに渡して、認識するようにする処理がここ
			 */
			_nyARDetectMarker = new NyARSingleDetectMarker(_nyARParam, _arCodes, width, _nyARRaster.getBufferReader().getBufferType());
			_nyARDetectMarker.setContinueMode(false);
			//
			_nyARGLUtil = new NyARGLUtil(_gl);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//カメラパラメータの計算
		_nyARGLUtil.toCameraFrustumRH(_nyARParam, _camera_projection);
	}

これで実行すれば、付属しているサンプルと同じ用に表示されると思います。