用于android的opengl es中射线拾取的交叉测试

时间:2015-01-05 22:26:36

标签: android opengl-es ray-picking

好的,所以我能够获得3d空间中的坐标以便触摸现在我需要测试该光线是否与三角形相交。我要问的是帮助理解测试类。 BTW此代码来自http://android-raypick.blogspot.ca/2012/04/first-i-want-to-state-this-is-my-first.html。我知道将ray和一个空的float数组传递给intersectRayAndTriangle()但是测试T是V0 [],V1 []和V2 []但是我在哪里得到它们?它们是我对象的转换坐标吗?如果是这样,我将如何实现具有多个三角形的对象?

我的代码是:

表面视图:

public class MGLSurface extends GLSurfaceView {

MRenderer mRenderer = new MRenderer();
public static int select_Touch=0;
public static boolean selectButtonOn = false;
float x,y;

static float touchX;
static float touchY;

public MGLSurface(Context context) {
    super(context);
   // setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    setRenderer(new MRenderer());
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    int action = event.getActionMasked();
    x = event.getX();
    y = event.getY();
    switch(action){
        case MotionEvent.ACTION_DOWN:
            return true;
        case MotionEvent.ACTION_MOVE:
            x = event.getX();
            y = event.getY();
            return true;
        case MotionEvent.ACTION_UP:
            if (selectButtonOn== true) {
                select_Touch = 1;
                touchX = event.getX();
                touchY = event.getY();
                requestRender();
            }
    }

    return true;
}


}

然后我的渲染器:

public class MRenderer implements GLSurfaceView.Renderer {
private final String TAG ="Ray Picked";

private int H,W;


Cube cube;
 float[] convertedSquare = new float[Cube.vertices.length];
 float[] resultVector = new float[4];
 float[] inputVector = new float[4];
MatrixGrabber matrixGrabber = new MatrixGrabber();


public MRenderer() {
    cube = new Cube();

}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glDisable(GL10.GL_DITHER);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
    gl.glClearColor(.8f,0f,.2f,1f);
    gl.glClearDepthf(1f);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    gl.glViewport(0,0,width,height);
    H = height;
    W = width;

    float ratio = (float) width/height;
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glFrustumf(-ratio,ratio,-1,1f,1,25);

}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glDisable(GL10.GL_DITHER);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 2, 0);
    matrixGrabber.getCurrentState(gl);
    // long time = SystemClock.uptimeMillis()% 400l;
    // float angle = 0.90f* ((int)time);
    gl.glRotatef(1,1,0,0);
    gl.glRotatef(10,0,0,5);

    cube.draw(gl);


//Converting object cords to 3d space
       for(int i =0; i < Cube.vertices.length;i = i+3){
     inputVector[0] = Cube.vertices[i];
     inputVector[1] = Cube.vertices[i+1];
     inputVector[2] = Cube.vertices[i+2];
     inputVector[3] = 1;
     Matrix.multiplyMV(resultVector, 0, matrixGrabber.mModelView, 0, inputVector, 0);
     convertedSquare[i] = resultVector[0]/resultVector[3];
     convertedSquare[i+1] = resultVector[1]/resultVector[3];
     convertedSquare[i+2] = resultVector[2]/resultVector[3];

      //Handle Touch in gl thread
    if (MGLSurface.selectButtonOn==true && MGLSurface.select_Touch==1 ) {
        this.Ray(gl, W, H, MGLSurface.touchX, MGLSurface.touchY);
        MainActivity.mHandler.sendEmptyMessage(1);
        MGLSurface.select_Touch = 0;
        Log.d(TAG, "Near Coord =" + Arrays.toString(MainActivity.P0));
        Log.d(TAG, "Far Coord =" + Arrays.toString(MainActivity.P1));


    }
    else {

    }

}}



public void Ray(GL10 gl, int width, int height, float xTouch, float yTouch) {
    matrixGrabber.getCurrentState(gl);

    int[] viewport = {0, 0, width, height};

    float[] nearCoOrds = new float[3];
    float[] farCoOrds = new float[3];
    float[] temp = new float[4];
    float[] temp2 = new float[4];
    // get the near and far ords for the click

    float winx = xTouch, winy =(float)viewport[3] - yTouch;

           // Log.d(TAG, "modelView is =" + Arrays.toString(matrixGrabber.mModelView));
         // Log.d(TAG, "projection view is =" + Arrays.toString(matrixGrabber.mProjection));

    int result = GLU.gluUnProject(winx, winy, 1.0f, matrixGrabber.mModelView, 0, 
matrixGrabber.mProjection, 0, viewport, 0, temp, 0);

    Matrix.multiplyMV(temp2, 0, matrixGrabber.mModelView, 0, temp, 0);
    if(result == GL10.GL_TRUE){
        nearCoOrds[0] = temp2[0] / temp2[3];
        nearCoOrds[1] = temp2[1] / temp2[3];
        nearCoOrds[2] = temp2[2] / temp2[3];

    }

    result = GLU.gluUnProject(winx, winy, 0, matrixGrabber.mModelView, 0,    
matrixGrabber.mProjection, 0, viewport, 0, temp, 0);
    Matrix.multiplyMV(temp2,0,matrixGrabber.mModelView, 0, temp, 0);
    if(result == GL10.GL_TRUE){
        farCoOrds[0] = temp2[0] / temp2[3];
        farCoOrds[1] = temp2[1] / temp2[3];
        farCoOrds[2] = temp2[2] / temp2[3];
    }
  MainActivity.P0 = farCoOrds;
   MainActivity.P1 = nearCoOrds;

}

}

测试类:

public class Tests {
public float[] V0;
public float[] V1;
public float[] V2;

public Tests(float[] V0, float[] V1, float[] V2){
    this.V0 =V0;
    this.V1 = V1;
    this.V2 = V2;
}


private static final float SMALL_NUM =  0.00000001f; // anything that avoids division overflow


// intersectRayAndTriangle(): intersect a ray with a 3D triangle
//    Input:  a ray R, and a triangle T
//    Output: *I = intersection point (when it exists)
//    Return: -1 = triangle is degenerate (a segment or point)
//             0 = disjoint (no intersect)
//             1 = intersect in unique point I1
//             2 = are in the same plane
public static int intersectRayAndTriangle(MRenderer R, Tests T, float[] I)
{
    float[]    u, v, n;             // triangle vectors
    float[]    dir, w0, w;          // ray vectors
    float     r, a, b;             // params to calc ray-plane intersect

    // get triangle edge vectors and plane normal
    u =  Vector.minus(T.V1, T.V0);
    v =  Vector.minus(T.V2, T.V0);
    n =  Vector.crossProduct(u, v);             // cross product

    if (Arrays.equals(n, new float[]{0.0f, 0.0f, 0.0f})){           // triangle is degenerate
        return -1;                 // do not deal with this case
    }
    dir =  Vector.minus(MainActivity.P1, MainActivity.P0);             // ray direction vector
   w0 = Vector.minus( MainActivity.P0 , T.V0);
    a = - Vector.dot(n,w0);
    b =  Vector.dot(n,dir);
    if (Math.abs(b) < SMALL_NUM) {     // ray is parallel to triangle plane
        if (a == 0){                // ray lies in triangle plane
            return 2;
        }else{
            return 0;             // ray disjoint from plane
        }
    }

    // get intersect point of ray with triangle plane
    r = a / b;
    if (r < 0.0f){                   // ray goes away from triangle
        return 0;                  // => no intersect
    }
    // for a segment, also test if (r > 1.0) => no intersect

    float[] tempI =  Vector.addition(MainActivity.P0,  Vector.scalarProduct(r, 
    dir));           // intersect point of ray and plane
    I[0] = tempI[0];
    I[1] = tempI[1];
    I[2] = tempI[2];

    // is I inside T?
    float    uu, uv, vv, wu, wv, D;
    uu =  Vector.dot(u,u);
    uv =  Vector.dot(u,v);
    vv =  Vector.dot(v,v);
    w =  Vector.minus(I, T.V0);
    wu =  Vector.dot(w,u);
    wv = Vector.dot(w,v);
    D = (uv * uv) - (uu * vv);

    // get and test parametric coords
    float s, t;
    s = ((uv * wv) - (vv * wu)) / D;
    if (s < 0.0f || s > 1.0f)        // I is outside T
        return 0;
    t = (uv * wu - uu * wv) / D;
    if (t < 0.0f || (s + t) > 1.0f)  // I is outside T
        return 0;

    return 1;                      // I is in T
}


}

0 个答案:

没有答案