JPCT-AE for Android 3D (三)----------拾取

       现在我们已经创建了一个多纹理的立方体,但是如何判断当前点击的是哪个面呢?下面我们来看看JPCT-AE拾取。

       在JPCT-AE的Wiki中已存在了对拾取的介绍:http://www.jpct.net/wiki/index.php/Picking。在Wiki中介绍了两种拾取方式,但是在Android中只支持第二中方式。原文如下:

The compatible way

This works with all renderers and all objects, but depending on the scene it might by a bit slower. It's the only one that is available in jPCT-AE. Unlike the former approach, this is actually a kind of collision detection, which is why it triggers collision events too. Just like above, you have to make your objects pickable. However, because it's a collision detection, this works different. Instead of using setSelectable(...), you have to use setCollisionMode(...). For example:

obj.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);

Like above, you need your 2D picking coordinates. With them, you need a direction vector in world space. This is simple:

SimpleVector dir=Interact2D.reproject2D3DWS(camera, frameBuffer, x, y).normalize();

Armed with this vector, you can now go to World and do

Object[] res=world.calcMinDistanceAndObject3D(camera.getPosition(), dir, 10000 /*or whatever*/);

The result is an Object[]-array with the Float-distance to the picked object in the first slot and the picked Object3D in the second. If nothing has been hit, the result will be [COLLISION_NONE, null].

现在通过修改我们之前的代码,来判断当前点击的立方体面。

private void CreateBox() {
		cube = new Object3D(0);
		
		// 前
		yi = new Object3D(2);
		yi.addTriangle(GetPoint(-30, -30, 30), 0.0f, 0.0f,
				GetPoint(30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, 30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("yi"));

		yi.addTriangle(GetPoint(30, -30, 30), 1.0f, 0.0f,
				GetPoint(30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, 30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("yi"));
		cube.addChild(yi);
		world.addObject(yi);	
		yi.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
		
		// 上
		shi = new Object3D(2);
		shi.addTriangle(GetPoint(-30, 30, 30), 0.0f, 0.0f,
				GetPoint(30, 30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("shi"));

		shi.addTriangle(GetPoint(30, 30, 30), 1.0f, 0.0f,
				GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("shi"));
		cube.addChild(shi);
		world.addObject(shi);	
		shi.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

		// 后
		zhu = new Object3D(2);
		zhu.addTriangle(GetPoint( -30, 30, -30), 0.0f, 0.0f,
				GetPoint(30, 30, -30), 1.0f, 0.0f, GetPoint(-30, -30, -30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("zhu"));

		zhu.addTriangle(GetPoint(30, 30, -30), 1.0f, 0.0f,
				GetPoint(30, -30, -30), 1.0f, 1.0f, GetPoint(-30, -30, -30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("zhu"));
		cube.addChild(zhu);
		world.addObject(zhu);	
		zhu.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
		
		// 下
		xing = new Object3D(2);
		xing.addTriangle(GetPoint(-30, -30, -30), 0.0f, 0.0f,
				GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(-30, -30, 30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("xing"));

		xing.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
				GetPoint(30, -30, 30), 1.0f, 1.0f, GetPoint( -30, -30, 30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("xing"));
		cube.addChild(xing);
		world.addObject(xing);	
		xing.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
		
		// 左
		wan = new Object3D(2);
		wan.addTriangle(GetPoint( -30, -30, -30), 0.0f, 0.0f,
				GetPoint(-30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("wan"));

		wan.addTriangle(GetPoint( -30, -30, 30), 1.0f, 0.0f,
				GetPoint(-30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
				0.0f, 1.0f, TextureManager.getInstance().getTextureID("wan"));
		cube.addChild(wan);
		world.addObject(wan);
		wan.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
		
		// 右
		wen = new Object3D(2);
		wen.addTriangle(GetPoint(30, -30, 30), 0.0f, 0.0f,
				GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(30, 30, 30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("wen"));

		wen.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
				GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(30, 30, 30), 0.0f,
				1.0f, TextureManager.getInstance().getTextureID("wen"));
		cube.addChild(wen);
		world.addObject(wen);	
		wen.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

		cube.strip();
		cube.build();
		world.addObject(cube);
		cube.setCulling(false);
		cube.scale( 0.4f);
		cube.rotateZ( 180);
		cube.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

在CBoxRander中添加如下方法:

public int Pickint( int fX, int fY){
		//fY = fb.getHeight() - fY;
		SimpleVector dir = Interact2D.reproject2D3DWS( cam, fb, fX, fY).normalize();
		Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 );
		
		Object3D picked = (Object3D)res[1];
		
		if( picked == null)
			return -1;
		
		if( picked.getID() == yi.getID())
			return 1;
		else  if( picked.getID() == shi.getID())
			return 2;
		else  if( picked.getID() == zhu.getID())
			return 3;
		else  if( picked.getID() == xing.getID())
			return 4;
		else  if( picked.getID() == wan.getID())
			return 5;
		else  if( picked.getID() == wen.getID())
			return 6;
		
		return -1;
	}

world.calcMinDistanceAndObject3D()返回的是一个包含两个元素的数组,res[0]为起点到焦点的距离,res[1]为当前被拾取的Object3D对象。当射线未与任何物体相交时,res[0]=COLLISION_NONE,res[1]=null.

在BoxView::onTouchEvent中添加如下代码

int a = mRander.Pickint( (int)me.getX(), (int)me.getY());

a就是我们选择的面的序列了。


你可能感兴趣的:(JPCT-AE for Android 3D (三)----------拾取)