现在我们已经创建了一个多纹理的立方体,但是如何判断当前点击的是哪个面呢?下面我们来看看JPCT-AE拾取。
在JPCT-AE的Wiki中已存在了对拾取的介绍:http://www.jpct.net/wiki/index.php/Picking。在Wiki中介绍了两种拾取方式,但是在Android中只支持第二中方式。原文如下:
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);
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());