2008年9月21日日曜日

NyARToolkit for Java: QtJavaで読み込んで JOGLで書き出す

追記(2010/06/08): NyARToolkit-2.3.2 MacOSX 10.6 / Eclipseについて書きました



先の例でVideoの読み込みはできたけど,書き出すのは普通にGraphicsに行列等文字列を書いてた.
そこで,まったくOpenGLとか知らない私が,NyARToolkit for Java付属のJOGLサンプルなどをつなぎ合わせて動かしてみようという試み.
間違っていたらごめんなさい.

環境:MacOS X 10.5.5 / Java 1.5

0.先の例のutilの作成(2.2)まではやっておく.

1.Javaプロジェクトを作成,'MyAR'とする.
1.1 先の例の3.2のようにプロジェクトのプロパティ/Java Build Path/プロジェクトタブに追加で'SampleARToolkit', 'SampleARToolkit_util'を加える.


2.libフォルダを用意.joglのライブラリを入れる.
2.1 ここから取得.https://jogl.dev.java.net/
2.2 libフォルダを作成して展開したフォルダをごっそり入れておく.
2.3 java build pathには'lib/jogl-1.1.2-pre-20080523-macosx-universal/lib/jogl.jar'と'lib/jogl-1.1.2-pre-20080523-macosx-universal/lib/glluegen-rt.jar'を追加.

3.NyARToolkit for Javaの'src.utils/jogl'下のファイルを入れる.
3.1 'jp/myatla.nyartoolkit.jogl.utils.GLNyARParam.java'をdndでsrcフォルダに入れる.
3.2 'jp/myatla.nyartoolkit.jogl.utils.GLNyARSingleDetectMarker.java'も同様にsrcフォルダに追加する.

4.どうしてもutilプロジェクト(先の記事でSampleARToolkit_utilsとしたモノ)内のファイルを編集する必要ができた…
4.1'src/jp/nyatla/nyartoolkit/qt/utils/QtNyARRaster_RGB.java'に以下のメソッドを追加.
src/jp/nyatla/nyartoolkit/qt/utils/QtNyARRaster_RGB.javaにメソッドを追加
 public byte[] get_Ref_buf() {
return this._ref_buf;
}


5.で,コードを作成.
5.1
src/MyAR.java
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import jp.nyatla.nyartoolkit.NyARException;

@SuppressWarnings("serial")
public class MyAR extends Frame {
public final static int SCREEN_X = 320;
public final static int SCREEN_Y = 240;

public MyAR() {
setTitle("MyAR");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setVisible(true);
setSize(SCREEN_X, SCREEN_Y);

try {
add(new MyGLCanvas());
} catch (NyARException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
new MyAR();
}
}


5.2
src/MyQtCameraCapture.java
import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.qt.utils.QtCameraCapture;
import jp.nyatla.nyartoolkit.qt.utils.QtCaptureListener;
import jp.nyatla.nyartoolkit.qt.utils.QtNyARRaster_RGB;

public class MyQtCameraCapture extends QtCameraCapture implements
QtCaptureListener {
private QtNyARRaster_RGB _raster;

public MyQtCameraCapture() throws NyARException {
super(MyAR.SCREEN_X, MyAR.SCREEN_Y, 30f);
setCaptureListener(this);

_raster = new QtNyARRaster_RGB(MyAR.SCREEN_X, MyAR.SCREEN_Y);
}

public void onUpdateBuffer(byte[] pixels) {
try {
_raster.setBuffer(pixels);
} catch (Exception e) {
e.printStackTrace();
}
}

public QtNyARRaster_RGB get_raster() {
return _raster;
}
}

5.3 (JOGLでのsampleを参考)
src/MyGLCanvas.java
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;

import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.core.NyARCode;
import jp.nyatla.nyartoolkit.core.types.NyARIntSize;
import jp.nyatla.nyartoolkit.jogl.utils.GLNyARParam;
import jp.nyatla.nyartoolkit.jogl.utils.GLNyARSingleDetectMarker;
import jp.nyatla.nyartoolkit.qt.utils.QtNyARRaster_RGB;

import com.sun.opengl.util.Animator;

@SuppressWarnings("serial")
public class MyGLCanvas extends GLCanvas implements GLEventListener {
private final String CARCODE_FILE = "./Data/patt.hiro";
private final String PARAM_FILE = "./Data/camera_para.dat";

private GL _gl;
private QtNyARRaster_RGB _raster;
private GLNyARSingleDetectMarker _nya;
private GLNyARParam _ar_param;

public MyGLCanvas() throws NyARException {
addGLEventListener(this);
setSize(MyAR.SCREEN_X, MyAR.SCREEN_Y);

MyQtCameraCapture _qtCapture = new MyQtCameraCapture();
_raster = _qtCapture.get_raster();
_qtCapture.start();
}

public void drawCube() {
int polyList = 0;
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 colours.
_gl.glCallList(polyList); // Draw the cube.
_gl.glPopMatrix(); // Restore world coordinate system.
}

public void display(GLAutoDrawable drawable) {
try {
if (!_raster.hasData()) {
return;
}
_gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

boolean is_marker_exist;
synchronized (_raster) {
is_marker_exist = _nya.detectMarkerLite(_raster, 100);
{
NyARIntSize rsize = _raster.getSize();
IntBuffer params = IntBuffer.allocate(4);
_gl.glDisable(GL.GL_TEXTURE_2D);
_gl.glGetIntegerv(GL.GL_VIEWPORT, params);
_gl.glPixelZoom(
1f * ((float) (params.get(2)) / (float) rsize.w),
-1f * ((float) (params.get(3)) / (float) rsize.h));
_gl.glWindowPos2f(0.0f, (float) rsize.h);
ByteBuffer buf = ByteBuffer.wrap(_raster.get_Ref_buf());
_gl.glDrawPixels(rsize.w, rsize.h, GL.GL_RGB,
GL.GL_UNSIGNED_BYTE, buf);
}

}
if (is_marker_exist) {

_gl.glMatrixMode(GL.GL_PROJECTION);
_gl.glLoadMatrixd(_ar_param.getCameraFrustumRH(), 0);
_gl.glMatrixMode(GL.GL_MODELVIEW);
_gl.glLoadIdentity();
_gl.glLoadMatrixd(_nya.getCameraViewRH(), 0);

drawCube();
}
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}

public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
boolean deviceChanged) {
}

public void init(GLAutoDrawable drawable) {
try {
// GL
_gl = drawable.getGL();
_gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

_ar_param = new GLNyARParam();
NyARCode ar_code = new NyARCode(16, 16);
_ar_param.loadARParamFromFile(PARAM_FILE);
_ar_param.changeScreenSize(320, 240);
_nya = new GLNyARSingleDetectMarker(_ar_param, ar_code, 80.0);
_nya.setContinueMode(false);
ar_code.loadARPattFromFile(CARCODE_FILE);

Animator _animator = new Animator(drawable);
_animator.start();
} catch (Exception e) {
e.printStackTrace();
}
}

public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
_gl.glViewport(0, 0, width, height);
_gl.glMatrixMode(GL.GL_PROJECTION);
_gl.glLoadIdentity();
_gl.glMatrixMode(GL.GL_MODELVIEW);
_gl.glLoadIdentity();
}
}
ボールド体の場所はキャプチャ画像をOpenGLの出力先に書くところ.NyARToolkitのサンプルは丁寧に作成されているらしくチェックとかいろいろしているっぽかった(理解力不足ですみません).で,それを決めうちとか , 無くても動くところを省くとか勝手にしてみた.2Dを3Dに書くのっていろいろたいへん!


以上でプロジェクトはこうなっている.


6.実行
6.1 'MyAR.java'を実行させるのだがこのときVM引数を指定する.
Run Configurationsを開いてArgumentsタブのVM argumentsに以下を入力.
'-Djava.library.path=${workspace_loc:SampleJOGL}/lib/jogl-1.1.2-pre-20080523-macosx-universal/lib'


で動くとこうなる.


JOGL(MyGLCanvas)の部分はコピーやつぎはぎです.問題あればご指摘ください.

ーー
感謝:
NyARToolkit for Java
注意(?):
当然,NyARToolkit自身とutilsとこのプロジェクトを一つのsrcにしてもいいんですよ.

0 件のコメント: