使用LibGDX,如何确定来自触摸手势的光线是否与包含多个三角形的网格相交?

时间:2015-05-27 12:37:58

标签: java android opengl-es libgdx raycasting

我正在开发一款Android应用程序,该应用程序使用手机传感器的相机方向移动3D对象。

我的项目基于以下教程:Libgdx tutorial以及您可以在此处下载的代码:source code。它运作良好。但是,我试图实现允许用户触摸3D立方体对象的功能,我失败了。 Intersector.intersectRayTriangles()始终返回false。

我是LibGDX和OpenGL的新手,所以我找不到解决方案。请帮我。提前谢谢。

本教程的所有者已经编写了一个方法来完成这项工作,但它不起作用。代码如下:

3D立方体对象( Cube.java ):

public class Cube extends Shape {
    public static final float vertexData[] = { 0.5f, 0.5f, 0.5f, -0.5f, 0.5f,
        0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,

        0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f,
        0.5f, -0.5f,

        0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
        0.5f, 0.5f,

        0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f,
        0.5f, -0.5f,

        -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
        -0.5f, 0.5f,

        -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f,
        -0.5f, 0.5f, };

    public static final float texData[] = { 0.0f, 0.0f, // quad/face 0/Vertex 0
        0.0f, 1.0f, // quad/face 0/Vertex 1
        1.0f, 1.0f, // quad/face 0/Vertex 2
        1.0f, 0.0f, // quad/face 0/Vertex 3

        1.0f, 1.0f, // quad/face 1/Vertex 4
        0.0f, 1.0f, // quad/face 1/Vertex 5
        0.0f, 0.0f, // quad/face 1/Vertex 6
        1.0f, 0.0f, // quad/face 1/Vertex 7

        0.0f, 0.0f, // quad/face 2/Vertex 8
        0.0f, 1.0f, // quad/face 2/Vertex 9
        1.0f, 1.0f, // quad/face 2/Vertex 10
        1.0f, 0.0f, // quad/face 2/Vertex 11

        1.0f, 1.0f, // quad/face 3/Vertex 12
        0.0f, 1.0f, // quad/face 3/Vertex 13
        0.0f, 0.0f, // quad/face 3/Vertex 14
        1.0f, 0.0f, // quad/face 3/Vertex 15

        1.0f, 1.0f, // quad/face 4/Vertex 16
        0.0f, 1.0f, // quad/face 4/Vertex 17
        0.0f, 0.0f, // quad/face 4/Vertex 18
        1.0f, 0.0f, // quad/face 4/Vertex 19

        1.0f, 1.0f, // quad/face 5/Vertex 20
        0.0f, 1.0f, // quad/face 5/Vertex 21
        0.0f, 0.0f, // quad/face 5/Vertex 22
        1.0f, 0.0f, // quad/face 5/Vertex 23
};

    public static final short facesVerticesIndex[][] = { { 0, 1, 2, 3 },
        { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 },
        { 16, 17, 18, 19 }, { 20, 21, 22, 23 } };

    public final static VertexAttribute verticesAttributes[] = new VertexAttribute[] {
        new VertexAttribute(Usage.Position, 3, "a_position"),
        new VertexAttribute(Usage.ColorPacked, 4, "a_color"),
        new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"), };


    public Cube(Context context, String textFilename) {
        super(context);
        textureFilename = textFilename;
        mesh = new Mesh[6];
        // Load the Libgdx splash screen texture
        texture = new Texture(Gdx.files.internal(textureFilename));
        texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

        // Create the 6 faces of the Cube
        for (int i = 0; i < 6; i++) {
            mesh[i] = new Mesh(true, 24, 4, verticesAttributes);
            int pIdx = 0;
            int tIdx = 0;
            float[] vertices = new float[144];
            for (int j = 0; j < vertices.length; ) {
                vertices[j++] = vertexData[pIdx++];
                vertices[j++] = vertexData[pIdx++];
                vertices[j++] = vertexData[pIdx++];
                vertices[j++] = Color.toFloatBits(255, 255, 255, 255);
                vertices[j++] = texData[tIdx++];
                vertices[j++] = texData[tIdx++];
            }

            mesh[i].setVertices(vertices);
            mesh[i].setIndices(Cube.facesVerticesIndex[i]);
        }
        intersectionIndices = new short[6][6];
        for (int i = 0; i < 6; i++) {
            short[] temp = new short[6];
            for (int j = 0; j < facesVerticesIndex.length; j++) {
                if (j <= 2) {
                    temp[j] = facesVerticesIndex[i][j];
                }
                if (j > 2) {
                    temp[3] = facesVerticesIndex[i][0];
                    temp[4] = facesVerticesIndex[i][2];
                    temp[5] = facesVerticesIndex[i][3];
                }
            }
            intersectionIndices[i] = temp;
        }
}

    public void render() {
        Gdx.gl10.glPushMatrix();
        float[] infilter = { virX, virY, virZ };
        float[] outfilter = this.filter.lowPass(infilter, 0.06f);
        Gdx.gl10.glTranslatef(outfilter[0], outfilter[1], outfilter[2]);
        Gdx.gl10.glRotatef(angle, xAxis, yAxis, zAxis);
        Gdx.gl10.glScalef(scaleX, scaleY, scaleZ);
        texture.bind();
        for (int i = 0; i < 6; i++) {
            mesh[i].render(GL10.GL_TRIANGLE_FAN, 0, 4);
        }
        texture.bind(0);
        Gdx.gl11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, accModelView, 0);
        if(this.index>0){
        //  modelView=new Matrix4(this.Parent.getShapes().get(this.index-1).accModelView).inv().val;
        Matrix4.mul(modelView,accModelView);
        }else{
            modelView = accModelView;
        }
        Gdx.gl10.glPopMatrix();

    }
}

我使用下面的方法来找到光线与立方体的交集:

public boolean isIntersected(Ray ray, float[] view) {
    radius = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)
            + Math.pow(z, 2));
    Matrix4.mul(view, modelView);
    Matrix4 mat = new Matrix4(view);
    float[] temp = new float[vertexData.length];
    for (int i = 0; i < vertexData.length; i += 3) {
        float[] vec = { vertexData[0 + i], vertexData[1 + i],
                vertexData[2 + i], 1 };
        Matrix4.mulVec(mat.val, vec);
        temp[0 + i] = vec[0];
        temp[1 + i] = vec[1];
        temp[2 + i] = vec[2];
    }
    for(int i=0;i<temp.length;i++){
        System.out.println(temp[i]);
    }
    Vector3 localIntersection = new Vector3();
    Vector3 globalIntersection = new Vector3();
    boolean intersectionOccured = false;
    for (int j = 0; j < mesh.length; j++) {
        if (Intersector.intersectRayTriangles(ray, temp,
                intersectionIndices[j], 3, localIntersection)) {
            intersectionOccured = true;
            if (!(globalIntersection.isZero())) {
                if (ray.origin.sub(localIntersection).len() < ray.origin
                        .sub(globalIntersection).len()) {
                    globalIntersection.set(localIntersection);

                }
            } else {
                globalIntersection.set(localIntersection);

            }
        }
    }
    if (!globalIntersection.isZero() && intersectionOccured) {
        listener.click(this, globalIntersection);

    }

    return false;
} 

在Screen.java中,我收到了触摸点的位置并将其传递给上述方法:

public Screen(Context context) {
    this.context = context;
    this.eventHandler = new EventHandler() {

        @Override
        public boolean tap(float x, float y, int count, int button) {
            Ray ray = camera.getPickRay(Gdx.input.getX(),
                    Gdx.input.getY(), 0, 0, Gdx.graphics.getWidth(),
                    Gdx.graphics.getHeight());
            c.isIntersected(ray, camera.view.getValues());
            return super.tap(x, y, count, button);

        }

        @Override
        public boolean pan(float x, float y, float deltaX, float deltaY) {

            return super.pan(x, y, deltaX, deltaY);
        }

        @Override
        public boolean zoom(float initialDistance, float distance) {

            return super.zoom(initialDistance, distance);
        }

    };
    this.gestureDetector = new GestureDetector(this.eventHandler);
}

0 个答案:

没有答案