好的,所以我能够获得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
}
}