元派遣プログラマの自称技術系ブログです。雑記とか自作のオープンソースプロジェクトの話とか。
Javaとか組込とかできます。お仕事ください。

もうちょい

演算系の問題点は全て解消。

JavaOpenGLの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で表示系に流してるところのカラーマップを修正すれば(とりあえず)完成。