2014-12-27 2 views
-1

나는 안드로이드 애플 리케이션에서 광선 따기를 구현하려고하고 있으며 참조 가이드로 http://android-raypick.blogspot.ca/2012/04/first-i-want-to-state-this-is-my-first.html을 사용 해왔다. 클래스를 가져오고 사이트의 일부 클래스를 복사하면 코드에 오류가 발생합니다. 그들은 어디에 코드를 넣을 지 잘 설명하지 못합니다. 나는 모든 것을 최신 OpenGL 버전으로 변환 할 것이고, 나중에 작업 코드를 얻고 이해하려고 노력할 것입니다. 많은 코드가 있지만 내가 가지고있는 것을 나열 할 것입니다. 이 게시물이 중복 될 수도 있지만 필자는 웹 전체를 둘러 보았고이 주제에 대한 정보를 많이 찾았지만 이미 예제로 사용할 수는 없으며 이해하기 위해 혼란 스러울 수는 없습니다.OpenGL에서 1 안드로이드 애플 리케이션을위한 광선 선택 도구를 구현하려고합니다

public class CadActivity extends ActionBarActivity { 

GLSurfaceView cadLayout; 
TextView xV = (TextView) findViewById(R.id.x); 
TextView yV = (TextView) findViewById(R.id.y); 
TextView zV = (TextView) findViewById(R.id.z); 





@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    cadLayout= new CadGlSurfaceView(this); 
    cadLayout.setGLWrapper(new GLSurfaceView.GLWrapper() { 
     @Override 
     public GL wrap(GL gl) { 
      return new MatrixTrackingGL(gl); 
     } 
    }); 
    setContentView(R.layout.activity_cad); 
    RelativeLayout v = (RelativeLayout) findViewById(R.id.surfacegl); 
    v.addView(cadLayout); 




} 

위 코드는 GL 래퍼의 주요 활동입니다. 이 다음 코드 내 렌더러입니다

public class CadGlSurfaceView extends GLSurfaceView { 
float x,y,sX,sY,fX,fY; 
CadActivity main; 


public CadGlSurfaceView(Context context) { 

    super(context); 

    setRenderer(new CadRenderer()); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
int action = event.getActionMasked(); 
x = event.getX(); 
y = event.getY(); 
    switch(action){ 
     case MotionEvent.ACTION_DOWN: 
      x = event.getX(); 
      y = event.getY(); 
      sX = event.getX(); 
      sY = event.getY(); 

      return true; 
     case MotionEvent.ACTION_MOVE: 
      x = event.getX(); 
      y = event.getY(); 
      return true; 
     case MotionEvent.ACTION_UP: 
      x = event.getX(); 
      y = event.getY(); 
      fX = event.getX(); 
      fY = event.getY(); 

      return true; 

    } 




    return true; 
    } 
} 

:

이 코드는 아래에있는 내 GLSurfaceView입니다

public class CadRenderer implements GLSurfaceView.Renderer { 

private GlObjects objects; 
MatrixGrabber matrixGrabber = new MatrixGrabber(); 
public CadRenderer(){ 
    objects = new GlObjects(); 

} 



@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig eglconfig) { 
    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); 
    int[] viewport = {0, 0, width, height}; 
    float ratio = (float) width/height; 
    gl.glMatrixMode(GL10.GL_PROJECTION); 
    gl.glLoadIdentity(); 
    gl.glFrustumf(-ratio,ratio,-1,1f,1,25); 
    matrixGrabber.getCurrentState(gl); 
    matrixGrabber.mModelView; 
    matrixGrabber.mProjection; 

} 

@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); 

    objects.draw(gl); 

    } 
} 

matrixGrabber.mModelView; matrixGrabber.mProjection; 이 두 코드에는 (Not a Statement) 빨간 선이 있습니다.

이것은 내 대상입니다. 나는 선을 그어서 몇 가지를 바꿀 필요가 있음을 알게 될 것입니다.

public class GlObjects { 
private float vertices[]={ 
    0f,1f, 
    1f,-1f, 
    -1f,-1f 
}; 

private short pIndex[]={0,1,2}; 

private ShortBuffer pBuff; 
private FloatBuffer vertBuff; 

public GlObjects(){ 
    ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length*4); 
    bBuff.order(ByteOrder.nativeOrder()); 
    vertBuff = bBuff.asFloatBuffer(); 
    vertBuff.put(vertices); 
    vertBuff.position(0); 

    ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length*2); 
    pbBuff.order(ByteOrder.nativeOrder()); 
    pBuff = pbBuff.asShortBuffer(); 
    pBuff.put(pIndex); 
    pBuff.position(0); 
} 

public void draw(GL10 gl){ 
    gl.glFrontFace(GL10.GL_CW); 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glVertexPointer(2,GL10.GL_FLOAT,0,vertBuff); 
    gl.glDrawElements(GL10.GL_TRIANGLES,pIndex.length,GL10.GL_UNSIGNED_SHORT,pBuff); 
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 

    } 
} 

이것은 웹 사이트의 레이 클래스입니다.

public class Ray { 
public Ray(GL10 gl, int width, int height, float xTouch, float yTouch) { 
    MatrixGrabber matrixGrabber = new MatrixGrabber(); 
    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]; 
    } 
    this.P0 = farCoOrds; 
    this.P1 = nearCoOrds; 
    } 

} 

this.P0 = farCoOrds; this.P1 = nearCoOrds; 아래에 빨간색 선이 표시되어 있습니다 (기호를 해결할 수 없음).

이 웹 사이트에서 삼각형 클래스는 다음과 같습니다

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

public Triangle(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(Ray R, Triangle 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(R.P1, R.P0);    // ray direction vector 
    w0 = Vector.minus(R.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(R.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 
    } 


} 

는 다음 웹 사이트에서 벡터 클래스를 지속.

public class Vector { 
// dot product (3D) which allows vector operations in arguments 
public static float dot(float[] u,float[] v) { 
    return ((u[X] * v[X]) + (u[Y] * v[Y]) + (u[Z] * v[Z])); 
} 
public static float[] minus(float[] u, float[] v){ 
    return new float[]{u[X]-v[X],u[Y]-v[Y],u[Z]-v[Z]}; 
} 
public static float[] addition(float[] u, float[] v){ 
    return new float[]{u[X]+v[X],u[Y]+v[Y],u[Z]+v[Z]}; 
} 
//scalar product 
public static float[] scalarProduct(float r, float[] u){ 
    return new float[]{u[X]*r,u[Y]*r,u[Z]*r}; 
} 
// (cross product) 
public static float[] crossProduct(float[] u, float[] v){ 
    return new float[]{(u[Y]*v[Z]) - (u[Z]*v[Y]),(u[Z]*v[X]) - (u[X]*v[Z]),(u[X]*v[Y]) - (u[Y]*v 
[X])}; 
} 
//mangnatude or length 
public static float length(float[] u){ 
    return (float) Math.abs(Math.sqrt((u[X] *u[X]) + (u[Y] *u[Y]) + (u[Z] *u[Z]))); 
} 

public static final int X = 0; 
public static final int Y = 1; 
public static final int Z = 2; 
} 

마찬가지로 저는 실제 예제를 얻고이 코드를 구현하는 방법을 이해하고 있다고 말했습니다.

답변

0

나는 안드로이드에서 비슷한 방법을 개발했습니다. 나는 GLSurfaceView에 많은 3D 구체를 표시하는 응용 프로그램을 사용했으며 클릭 한 구를 찾기 위해 광선 선택을 사용했습니다.

다음은이 코드입니다. 희망이 당신을 도와줍니다.

private void findTouchedSphere() 
    { 
     float[] view = new float[3]; 

     float[] cameraLookAt = new float[] { ... }; // the x/y/z of the point the camera is looking at 
     float[] cameraPosition = new float[] { ... ; // the x/y/z of the position of the camera 

     view[0] = cameraLookAt[0] - cameraPosition[0]; 
     view[1] = cameraLookAt[1] - cameraPosition[1]; 
     view[2] = cameraLookAt[2] - cameraPosition[2]; 

     normalizeVector(view); // make sure the view vector is a unit vector (|view| = 1) 

     float[] h = new float[3]; 
     float[] cameraUp = new float[] { ... }; // the up vector passed in GLU.gluLookAt 

     h[0] = view[1] * cameraUp[2] - view[2] * cameraUp[1]; 
     h[1] = view[2] * cameraUp[0] - view[0] * cameraUp[2]; 
     h[2] = view[0] * cameraUp[1] - view[1] * cameraUp[0]; 
     normalizeVector(h); 

     float[] v = new float[3]; 

     v[0] = h[1] * view[2] - h[2] * view[1]; 
     v[1] = h[2] * view[0] - h[0] * view[2]; 
     v[2] = h[0] * view[1] - h[1] * view[0]; 
     normalizeVector(v); 

     float radians = 45f * (float)Math.PI/180f; // 45f is the degree I pass in GLU.gluPerspective method 

     //minCamDistance is the minimum camera distance I pass in GLU.gluPerspective 
     float vLength = (float)Math.tan(radians/2f) * minCamDistance; 
     float hLength = vLength * mScreenWidth/mScreenHeight; 

     v[0] *= vLength; 
     v[1] *= vLength; 
     v[2] *= vLength; 

     h[0] *= hLength; 
     h[1] *= hLength; 
     h[2] *= hLength; 

     // mTouchX, mTouchY are the screen coordinates of the touch 
     // mScreenWidth, mScreenHeight are the screen dimensions 
     float x = mTouchX - mScreenWidth/2f; 
     float y = mScreenHeight/2f - mTouchY; 

     x /= mScreenWidth/2f; 
     y /= mScreenHeight/2f; 

     float[] pos = new float[3]; 

     pos[0] = cameraPosition[0] + view[0] * minCamDistance + h[0] * x + v[0] * y; 
     pos[1] = cameraPosition[1] + view[1] * minCamDistance + h[1] * x + v[1] * y; 
     pos[2] = cameraPosition[2] + view[2] * minCamDistance + h[2] * x + v[2] * y; 

     float[] dir = new float[3]; 
     dir[0] = pos[0] - cameraPosition[0]; 
     dir[1] = pos[1] - cameraPosition[1]; 
     dir[2] = pos[2] - cameraPosition[2];  

     float scalar; 

     float[] startingPos = new float[] { cameraPosition[0], cameraPosition[1], cameraPosition[2]}; 
     float[] currentPosition = new float[3]; 
     float distance; 

     for (Sphere sphere : mSpheres) 
     { 
      scalar = (sphere.getZ() - cameraPosition[2])/dir[2]; 
      currentPosition[0] = cameraPosition[0] + scalar * dir[0]; 
      currentPosition[1] = cameraPosition[1] + scalar * dir[1]; 

      distance = (float)Math.sqrt((currentPosition[0] - sphere.getPosition().x) * (currentPosition[0] - sphere.getPosition().x) + 
        (currentPosition[1] - sphere.getPosition().y) * (currentPosition[1] - sphere.getPosition().y)); 

      if (distance <= 6) // 6 is the sphere size 
      { 
       performSomeActionOnHitSphere(sphere); 
       return; 
      } 

     } 
    } 

평준화 벡터있어서

private void normalizeVector(float[] vector) 
    { 
     float length = (float)Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]); 
     vector[0] /= length; 
     vector[1] /= length; 
     vector[2] /= length; 
    } 
관련 문제