3D сбор с глес

1

Я пытаюсь сделать 3D-сбор, когда пользователь забирает экран телефона Android.

Он работает иногда, но когда я поворачиваю экран → луч не попадает в сферу

Я вложу исходный код в то, что у меня есть до сих пор:

a) класс renderer.java:

... // variables used
    public static   picking gPicker     = null;   
    public static   vector3 campos      = new vector3(0,0, 500);
    public static   vector3 sphpos      = new vector3(60,-40,0);
...




... // this function is called when user taps Screen 
public void screenWasTapped(vector2 touchcoords) 
{
    // get current time
    now = System.currentTimeMillis();

    // can shoot/tap every 100 msecs., not earlyer.
    if (now > mLastFiredTime + mInterval) 
    {
        // do we have a valid GL context?
        if(gGL!=null)
        {   
            // screen was tapped , so call "pick" function wich will check if ray hits sphere wich is located at "sphpos".
            gPicker.pick(gGL, gScreenWidth, gScreenHeight, touchcoords.x, touchcoords.y);

            // update last time
            mLastFiredTime = now;
        }
    }
}
....

Это настройки GL OnSurfaceChanged:

public void onSurfaceChanged(GL10 gl, int width, int height) 
{
    // To prevent divide by zero
    if (height == 0) height = 1;   
    float aspect = (float) width/height;

    // Set the viewport (display area) to cover the entire window
    gl.glViewport(0, 0, width, height);

    // Setup perspective projection, with aspect ratio matches viewport
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();                
    // Use perspective projection
    GLU.gluPerspective(gl, 60.0f, aspect, 0.1f, 5000.f);

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

    // Fast Perspective Calculations
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); 
    gl.glEnable(GL10.GL_TEXTURE_2D);


    // Enable GL Blending.
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

    // Drawing order & culling face settings.
    gl.glFrontFace(GL10.GL_CW);     // Front face in counter-clockwise orientation
    gl.glEnable(GL10.GL_CULL_FACE);     // Enable cull face
    gl.glCullFace(GL10.GL_BACK);        // Cull the back face (don't display)


    gScreenWidth  = width;
    gScreenHeight = height; 
}

... и вот как я рисую сцену:

public void onDrawFrame(GL10 gl) 
{
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    gTimer.startupdate();
    float dt = gTimer.getElapsed();

    gl.glLoadIdentity();
    gl.glTranslatef(-campos.x, -campos.y, -campos.z);
    gl.glRotatef(tableRotXAngle, 1, 0, 0); 
    gl.glRotatef(tableRotYAngle, 0, 1, 0f);


        gl.glColor4f(0,1,1,1);
        gl.glPushMatrix();
        gl.glTranslatef(sphpos.x,sphpos.y,sphpos.y); 
            newgame.gPyramid.render(gl);            // draw pyramid at 3d location specified by "sphpos"
        gl.glPopMatrix();
        gl.glColor4f(1,1,1,1);



        doGameAI(dt);
        doDisplayHUD(gl);

    gTimer.stopupdate();
    gl.glFlush();
}

ВАЖНОЕ ЗАМЕЧАНИЕ: вращение камеры с дугой, камера поворачивается, всегда смотря на центральные координаты (0,0,0) и переводится на 500 единиц назад (см. Инициализацию campos).

б) класс "picker.java":

    public class picking 
    {

   picking(GL10 gl)
   {
    MatrixGrabber mg = new MatrixGrabber();
    mg.getCurrentState(gl);
   }

(UPDATED)
public void pick(GL10 gl, int width, int height, float xTouch, float yTouch) 
{
    MatrixGrabber mg = new MatrixGrabber();
    mg.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];

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

    displayMatrix(mg.mModelView);
    displayMatrix(mg.mProjection);



    int result = GLU.gluUnProject(winx, winy, 0.0f, mg.mModelView, 0, mg.mProjection, 0, viewport, 0, temp, 0);
    // Matrix.multiplyMV(temp2, 0, mg.mModelView, 0, temp, 0);
    if(result == GL10.GL_TRUE){
        nearCoOrds[0] = temp[0] / temp[3];
        nearCoOrds[1] = temp[1] / temp[3];
        nearCoOrds[2] = temp[2] / temp[3];

    }



    Log.d("redwing", " ---> near pos "  + Float.toString(nearCoOrds[0]) + "," 
                                        + Float.toString(nearCoOrds[1]) + "," 
                                        + Float.toString(nearCoOrds[2]));

    result = GLU.gluUnProject(winx, winy, 1.0f , mg.mModelView, 0, mg.mProjection, 0, viewport, 0, temp, 0);
    // Matrix.multiplyMV(temp2,0, mg.mModelView, 0, temp, 0);
    if(result == GL10.GL_TRUE){
        farCoOrds[0] = temp[0] / temp[3];
        farCoOrds[1] = temp[1] / temp[3];
        farCoOrds[2] = temp[2] / temp[3];
    }

    Log.d("redwing", " ---> far pos "   + Float.toString(farCoOrds[0]) + "," 
                                        + Float.toString(farCoOrds[1]) + "," 
                                        + Float.toString(farCoOrds[2]));



    vector3 rayDirection = new vector3(farCoOrds[0]-nearCoOrds[0], farCoOrds[1]-nearCoOrds[1], farCoOrds[2]-nearCoOrds[2]);

    Log.d("redwing", " ---> raylen ="+ Float.toString(rayDirection.getLength()));

    rayDirection.setUnit();

    Log.d("redwing", " ---> dir "   + Float.toString(rayDirection.x) + "," 
                                    + Float.toString(rayDirection.y) + "," 
                                    + Float.toString(rayDirection.z));



    if(rayHitSphere(renderer.campos, rayDirection, renderer.sphpos, 10))
    {
        Log.e("redwing", "****************");
        Log.e("redwing", "ray hits OBJECT!");
        Log.e("redwing", "****************");
    }


}      


boolean rayHitSphere(vector3 rayPos, vector3 rayDir, vector3 sphereCntr, float radius)
{
      vector3 w = rayPos.sub(sphereCntr);   
      float A = rayDir.dot(rayDir);         
      float B = 2*w.dot(rayDir);            
      float C = w.dot(w) - radius*radius;   

      float D = B*B-4.0f*A*C;

      if(D>=0.0f)
      return true;
      else 
      return false;
    }


void displayMatrix(float[] m, String tag)
{
    for(byte i=0;i<4;i++)
    {
        Log.v("redbase "+tag, "mtx" + Byte.toString(i) + " - "  + new DecimalFormat("#.####").format(m[i*4+0])+","
                                                                + new DecimalFormat("#.####").format(m[i*4+1])+","
                                                                + new DecimalFormat("#.####").format(m[i*4+2])+","
                                                                + new DecimalFormat("#.####").format(m[i*4+3]));
    }
}

}

Просто не знаю, где я иду не так здесь. :( Pleease help !!

     Here are some values from Eclipse console when User tapped screen:
     (UPDATED - i get a Hit!)
    <<< NOT ROTATED SCENE >>
    06-02 12:15:22.611: D/redwing(5524): screen resolution 480x764
    06-02 12:15:22.611: D/redwing(5524): tapped coordinate ( 317.07507,426.2164
    06-02 12:15:22.621: V/redbase(5524): mtx0 - 1,0,0,0
    06-02 12:15:22.631: V/redbase(5524): mtx1 - 0,1,0,0
    06-02 12:15:22.631: V/redbase(5524): mtx2 - 0,0,1,0
    06-02 12:15:22.631: V/redbase(5524): mtx3 - 0,0,-500,1
    06-02 12:15:22.641: V/redbase(5524): mtx0 - 2.7568,0,0,0
    06-02 12:15:22.641: V/redbase(5524): mtx1 - 0,1.7321,0,0
    06-02 12:15:22.641: V/redbase(5524): mtx2 - 0,0,-1,-1
    06-02 12:15:22.651: V/redbase(5524): mtx3 - 0,0,-0.2,0
    06-02 12:15:22.651: D/redwing(5524):  ---> near pos 0.011649653,-0.0066829454,499.9
    06-02 12:15:22.661: D/redwing(5524):  ---> far pos 581.6618,-333.6764,-4493.4097
    06-02 12:15:22.661: D/redwing(5524):  ---> raylen =5038.134
    06-02 12:15:22.661: D/redwing(5524):  ---> dir 0.115449525,-0.06622883,-0.991103
    06-02 12:15:22.661: E/redwing(5524): ****************
    06-02 12:15:22.661: E/redwing(5524): ray hits OBJECT!
    06-02 12:15:22.661: E/redwing(5524): ****************


    <<< ROTATED SCENE!!  UPDATED - Still NO HIT!  >>
    06-02 12:15:30.671: D/redwing(5524): screen resolution 480x764
    06-02 12:15:30.671: D/redwing(5524): tapped coordinate ( 337.04843,440.11392
    06-02 12:15:30.671: V/redbase(5524): mtx0 - 0.9684,0.1802,0.1725,0
    06-02 12:15:30.671: V/redbase(5524): mtx1 - 0,0.6913,-0.7226,0
    06-02 12:15:30.681: V/redbase(5524): mtx2 - -0.2495,0.6997,0.6695,0
    06-02 12:15:30.681: V/redbase(5524): mtx3 - 0,0,-500,1
    06-02 12:15:30.681: V/redbase(5524): mtx0 - 2.7568,0,0,0
    06-02 12:15:30.681: V/redbase(5524): mtx1 - 0,1.7321,0,0
    06-02 12:15:30.681: V/redbase(5524): mtx2 - 0,0,-1,-1
    06-02 12:15:30.681: V/redbase(5524): mtx3 - 0,0,-0.2,0
    06-02 12:15:30.681: D/redwing(5524):  ---> near pos 86.22043,-361.2092,334.655
    06-02 12:15:30.691: D/redwing(5524):  ---> far pos -144.60953,2943.3904,-3498.0571
    06-02 12:15:30.691: D/redwing(5524):  ---> raylen =5065.9
    06-02 12:15:30.691: D/redwing(5524):  ---> dir -0.04556544,0.65232235,-0.7565708
  • если я не поворачиваю сцену, тогда у меня есть Хит!
  • но..если я вращаю сцену, тогда НЕТ ударить :(
Теги:
opengl-es
3d

2 ответа

0

Из первоначального прохода вашего кода он выглядит как проблема изменения разрешения экрана. Кажется, что ваш код не меняет ширину и высоту при повороте экрана. Это может быть выключено, но это выделяется как возможная проблема.

0

Не 100% положительный. Я понимаю весь код, но мне кажется, что вы не должны умножать результат gluUnproject с матрицей просмотра модели?

Если unproject дает местоположение щелчка в мировых координатах, и вы тестируете позицию шара в мировых координатах, я не понимаю, почему вы преобразовываете непроект в модельное представление.

Если вы хотите конвертировать клики в пространство камеры, вам также необходимо будет изменить местоположение вашей сферы, что я не вижу.

  • 0
    Хорошо, тогда два шага: 1) преобразовать сферу pos с помощью модели view mtx и 2) удалить Matrix.multiplyMV (temp2,0, mg.mModelView, 0, temp, 0); линии (есть 2), верно? вернусь сейчас с результатом.
  • 0
    @redbase: Вам, вероятно, следует сделать одно или другое, выполнение того и другого будет столь же неверным, как и то, с чего вы начали. Попробуйте просто удалить умножение вида модели на результат без проекта и оставить сферу pos такой, какая она есть.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню