演算系の問題点は全て解消。
JavaとOpenGLのProjection配列は互換性が有るけど、ほんの少しだけ要素をいじる必要があった。
場所はProjection行列の、[2][2]と[2][3]。そこに-1を書けて、ARToolkitの演算を通してからtransposeすればOK
こんなかんじ
//Projectionの計算 q[0][0] = (2.0 * p[0][0] / (width - 1)); q[0][1] = (2.0 * p[0][1] / (width - 1)); q[0][2] = -((2.0 * p[0][2] / (width - 1)) - 1.0); q[0][3] = 0.0; q[1][0] = 0.0; q[1][1] = -(2.0 * p[1][1] / (height - 1)); q[1][2] = -((2.0 * p[1][2] / (height - 1)) - 1.0); q[1][3] = 0.0; q[2][0] = 0.0; q[2][1] = 0.0; q[2][2] = (view_distance_max + view_distance_min)/(view_distance_min - view_distance_max); q[2][3] = 2.0 * view_distance_max * view_distance_min / (view_distance_min - view_distance_max); q[3][0] = 0.0; q[3][1] = 0.0; q[3][2] = -1.0; q[3][3] = 0.0; q[2][2]=q[2][2]*-1; q[2][3]=q[2][3]*-1; double[] tmp_projection=new double[16]; for (i = 0; i < 4; i++) { // Row. // First 3 columns of the current row. for (j = 0; j < 3; j++) { // Column. tmp_projection[i + j*4] =( q[i][0] * trans[0][j] + q[i][1] * trans[1][j] + q[i][2] * trans[2][j]); } // Fourth column of the current row. tmp_projection[i + 3*4]= q[i][0] * trans[0][3] + q[i][1] * trans[1][3] + q[i][2] * trans[2][3] + q[i][3]; } m_projection=new Transform3D(tmp_projection); m_projection.transpose(); return m_projection;
と、そうすると、ちゃんとARToolkitがJava3Dの世界で動くようになる。
サンプルコードはこんな感じになる予定。
public class NyARJava3D extends JFrame implements NyARSingleMarkerBehaviorListener { private final String CARCODE_FILE ="../../Data/patt.hiro"; private final String PARAM_FILE ="../../Data/camera_para.dat"; //NyARToolkit関係 private NyARSingleMarkerBehaviorHolder nya_behavior; private J3dNyARParam ar_param; //universe関係 private Canvas3D canvas; private Locale locale; private VirtualUniverse universe; public static void main(String[] args) { try{ NyARJava3D frame = new NyARJava3D(); frame.setVisible(true); Insets ins=frame.getInsets(); frame.setSize(320+ins.left+ins.right,240+ins.top+ins.bottom); frame.startCapture(); }catch(Exception e){ e.printStackTrace(); } } public void onUpdate(boolean i_is_marker_exist,Transform3D i_transform3d) { System.out.println(i_is_marker_exist); } public void startCapture() throws Exception { nya_behavior.start(); } public void onUpdateCaptureImage(J3dNyARRaster_RGB i_new_raster) { try{ }catch(Exception e){ e.printStackTrace(); } } public NyARJava3D() throws Exception { super("Java3D Example NyARToolkit"); //NyARToolkitの準備 NyARCode ar_code =new NyARCode(16,16); ar_code.loadFromARFile(CARCODE_FILE); ar_param=new J3dNyARParam(); ar_param.loadFromARFile(PARAM_FILE); ar_param.changeSize(320,240); //localeの作成とlocateとviewの設定 universe = new VirtualUniverse(); locale = new Locale( universe ); canvas=new Canvas3D( SimpleUniverse.getPreferredConfiguration()); View view = new View(); ViewPlatform viewPlatform = new ViewPlatform(); view.attachViewPlatform( viewPlatform ); view.addCanvas3D(canvas); view.setPhysicalBody( new PhysicalBody() ); view.setPhysicalEnvironment( new PhysicalEnvironment()); //視界の設定(カメラ設定から取得) Transform3D camera_3d=ar_param.getCameraTransform(); view.setCompatibilityModeEnable(true); view.setProjectionPolicy(View.PERSPECTIVE_PROJECTION); view.setLeftProjection(camera_3d); //視点設定(0,0,0から、Y軸を180度回転してZ+方向を向くようにする。) TransformGroup viewGroup = new TransformGroup(); Transform3D viewTransform = new Transform3D(); viewTransform.rotY(Math.PI); viewTransform.setTranslation(new Vector3d(0.0,0.0,0.0)); viewGroup.setTransform( viewTransform ); viewGroup.addChild( viewPlatform ); BranchGroup viewRoot = new BranchGroup(); viewRoot.addChild( viewGroup ); locale.addBranchGraph( viewRoot ); //バックグラウンドの作成 Background background =new Background(); BoundingSphere bounds = new BoundingSphere(); bounds.setRadius( 10.0 ); background.setApplicationBounds(bounds); background.setImageScaleMode(Background.SCALE_FIT_ALL); background.setCapability(Background.ALLOW_IMAGE_WRITE); BranchGroup root = new BranchGroup(); root.addChild(background); //TransformGroupで囲ったシーングラフの作成 TransformGroup transform=new TransformGroup(); transform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); transform.addChild(createSceneGraph()); root.addChild(transform); //NyARToolkitのBehaviorを作る。(マーカーサイズはメートルで指定すること) nya_behavior=new NyARSingleMarkerBehaviorHolder(ar_param,15f,ar_code,0.08); //Behaviorに連動するグループをセット nya_behavior.setTransformGroup(transform); nya_behavior.setBackGround(background); //出来たbehaviorをセット root.addChild(nya_behavior.getBehavior()); nya_behavior.setUpdateListener(this); //表示ブランチをLocateにセット locale.addBranchGraph(root); //ウインドウの設定 setLayout(new BorderLayout()); add(canvas,BorderLayout.CENTER); } /** * シーングラフを作って、そのノードを返す。 * このノードは40mmの色つきナタデココを表示するシーン。z軸を基準に20mm上に浮かせてる。 * @return */ private Node createSceneGraph() { TransformGroup tg=new TransformGroup(); Transform3D mt=new Transform3D(); mt.setTranslation(new Vector3d(0.00,0.0,20*0.001)); // 大きさ 40mmの色付き立方体を、Z軸上で40mm動かして配置) tg.setTransform(mt); tg.addChild(new ColorCube(20*0.001)); return tg; } }
あとはBGRをRGBで表示系に流してるところのカラーマップを修正すれば(とりあえず)完成。