2011-07-14 23 views
6

Android OpenGL-ES 2.0 sürümündeyim ve beraberinde gelen tüm sınırlamalardan sonra, 2D ekran dokunuşlarını sahip olduğum 3B noktalara nasıl alacağımı anlayamıyorum. Doğru sonuçları alamıyorum.Android OpenGL 3D toplama

Nokta bulutuna bir ışın vurmaya çalışıyorum, böylece noktalarımın mesafelerini ışınla karşılaştırarak en yakın noktayı bulabiliyorum.

public class OpenGLRenderer extends Activity implements GLSurfaceView.Renderer { 
    public PointCloud ptCloud; 
    MatrixGrabber mg = new MatrixGrabber(); 
... 
    public void onDrawFrame(GL10 gl) { 

     gl.glDisable(GL10.GL_COLOR_MATERIAL); 
     gl.glDisable(GL10.GL_BLEND); 
     gl.glDisable(GL10.GL_LIGHTING); 

     //Background drawing 
     if(customBackground) 
      gl.glClearColor(backgroundRed, backgroundGreen, backgroundBlue, 1.0f); 
     else 
      gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

     if (PointCloud.doneParsing == true) { 
      if (envDone == false) 
       setupEnvironment(); 

      // Clears the screen and depth buffer. 
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

      gl.glMatrixMode(GL10.GL_PROJECTION); 
      gl.glLoadIdentity(); 
      GLU.gluPerspective(gl, 55.0f, (float) screenWidth/(float) screenHeight, 10.0f ,10000.0f); 

      gl.glMatrixMode(GL10.GL_MODELVIEW); 

      gl.glLoadIdentity(); 
      GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, 
           centerX, centerY, centerZ, 
           upX, upY, upZ); 

      if(pickPointTrigger) 
       pickPoint(gl); 


      gl.glPushMatrix(); 

      gl.glTranslatef(_xTranslate, _yTranslate, _zTranslate); 
      gl.glTranslatef(centerX, centerY, centerZ); 
      gl.glRotatef(_xAngle, 1f, 0f, 0f); 
      gl.glRotatef(_yAngle, 0f, 1f, 0f); 
      gl.glRotatef(_zAngle, 0f, 0f, 1f); 
      gl.glTranslatef(-centerX, -centerY, -centerZ); 

      ptCloud.draw(gl); 

      gl.glPopMatrix(); 
     } 
    } 
} 

İşte benim toplama işlevim. Sadece hata ayıklama amacıyla ekranın ortasına yerini belirledik:

public void pickPoint(GL10 gl){ 

     mg.getCurrentState(gl); 

     double mvmatrix[] = new double[16]; 
     double projmatrix[] = new double[16]; 
     int viewport[] = {0,0,screenWidth, screenHeight}; 

     for(int i=0 ; i<16; i++){ 
      mvmatrix[i] = mg.mModelView[i]; 
      projmatrix[i] = mg.mProjection[i]; 
     } 

     mg.getCurrentState(gl); 

     float realY = ((float) (screenHeight) - pickY); 
     float nearCoords[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 
     float farCoords[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 


     GLU.gluUnProject(screenWidth/2, screenHeight/2, 0.0f, mg.mModelView, 0, mg.mProjection, 0, 
        viewport, 0, nearCoords, 0); 
     GLU.gluUnProject(screenWidth/2, screenHeight/2, 1.0f, mg.mModelView, 0, mg.mProjection, 0, 
        viewport, 0, farCoords, 0); 

     System.out.println("Near: " + nearCoords[0] + "," + nearCoords[1] + "," + nearCoords[2]); 
     System.out.println("Far: " + farCoords[0] + "," + farCoords[1] + "," + farCoords[2]); 



     //Plot the points in the scene 
     nearMarker.set(nearCoords); 
     farMarker.set(farCoords); 
     markerOn = true; 

     double diffX = nearCoords[0] - farCoords[0]; 
     double diffY = nearCoords[1] - farCoords[1]; 
     double diffZ = nearCoords[2] - farCoords[2]; 

     double rayLength = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2) + Math.pow(diffZ, 2)); 
     System.out.println("rayLength: " + rayLength); 

     pickPointTrigger = false; 
    } 

persepctive zNear değiştirme ve Uzak beklenen sonuçları yok, nasıl bir 1,0-1000,0 perspektiften uzak noktası olabilir 11 birim uzakta mı?

GLU.gluPerspective(gl, 55.0f, (float) screenWidth/(float) screenHeight, 1.0f ,100.0f); 
..... 
07-18 11:23:50.430: INFO/System.out(31795): Near: 57.574852,-88.60514,37.272636 
07-18 11:23:50.430: INFO/System.out(31795): Far: 0.57574844,0.098602295,0.2700405 
07-18 11:23:50.430: INFO/System.out(31795): rayLength: 111.74275719790872 

GLU.gluPerspective(gl, 55.0f, (float) width/(float) height, 10.0f , 1000.0f); 
... 
07-18 11:25:12.420: INFO/System.out(31847): Near: 5.7575016,-7.965394,3.6339219 
07-18 11:25:12.420: INFO/System.out(31847): Far: 0.057574987,0.90500546,-0.06634784 
07-18 11:25:12.420: INFO/System.out(31847): rayLength: 11.174307289026638 

Kodumda gördüğünüz herhangi bir öneri veya umarım hatalar aranıyor. Çok takdir edildi. Elimden geldiğince çok kandırıyorum (bu bir süredir bir problem olmuştur).

cevap

9

Bu konuda da çalışıyorum - bu çok rahatsız edici bir tahriş problemi. İki potansiyel potansiyelim var: 1. Her nasılsa, sonuçta elde edilen z, kameranın nerede olduğuna bağlı ve beklediğiniz gibi değil. Z kamerası 0 olduğunda, sonuç z z olur -1, winZ ne olursa olsun. Şimdiye kadar esas olarak sonuçta ortaya çıkan z'ye baktım, bu yüzden diğer koordinatlarda tam rakamlarım yok, ama şimdi kodum ve kodunuzla uğraştım ve şimdi rapor ettim. ışın uzunluğu kameradan ne kadar uzaklaşır (0,0,0). (0,0,0) 'da, ışın uzunluğunun 0 olduğu bildirildi. Bir saat kadar önce, bir dizi puan topladım (cameraZ, winZ, resultZ) ve bunları Mathematica'ya taktım. Sonuç hiperbolik bir şeyi işaret ediyor gibi görünüyor; sabit olan değişkenlerden biri ile diğeri elde edilen z'nin sabit değişkene bağlı olarak değişme oranı ile lineer olarak değişmesine neden olur.

İkinci ipucum http://www.gamedev.net/topic/420427-gluunproject-question/; kılıç bir formül tırnak:

WINZ = (1.0f/fNear-1.0f/fDistance)/(1.0f/fNear-1.0f/fFar)

Şimdi, bu ile maç görünmüyor topladığım veriler, ancak muhtemelen bir göz atmaya değer. Sanırım bu şeyin matematiğinin nasıl çalıştığını anlayabileceğimi ve neyin yanlış olduğunu anlayabileceğimi göreceğim. Bir şey öğrenirsen haberim olsun. : - - 0,0003149873867479971 x^2 - 0.8633277851535017 y + 9,990256062051143 x y + 8.767260632968973 *^9 y^2

Wolfram Alpha böylece gibi çizer

-0,11072114015496763 - 10.000231721597817 x: Ah, ayrıca, burada toplanan verilere uydurulan formülü http://www.wolframalpha.com/input/?i=Plot3D[-0.11072114015496763%60+-+10.000231721597817%60+x+-++++0.0003149873867479971%60+x^2+-+0.8633277851535017%60+y+%2B++++9.990256062051143%60+x+y+%2B+8.767260632968973%60*^-9+y^2+%2C+{x%2C+-15%2C++++15}%2C+{y%2C+0%2C+1}]


AHA! Başarı! Söylediğim kadarıyla, gluUnProject sadece düz. Ya da hiç kimse onu nasıl kullanacağını anlamaz. Her neyse, gerçekten bir şekilde ekrana çekmek için kullandıkları şey gibi görünen gluProject işlevini düzgün bir şekilde çözen bir işlev yaptım!Bu anda aşağıdaki genel değişkenler kabul

public float[] unproject(float rx, float ry, float rz) {//TODO Factor in projection matrix 
    float[] modelInv = new float[16]; 
    if (!android.opengl.Matrix.invertM(modelInv, 0, mg.mModelView, 0)) 
     throw new IllegalArgumentException("ModelView is not invertible."); 
    float[] projInv = new float[16]; 
    if (!android.opengl.Matrix.invertM(projInv, 0, mg.mProjection, 0)) 
     throw new IllegalArgumentException("Projection is not invertible."); 
    float[] combo = new float[16]; 
    android.opengl.Matrix.multiplyMM(combo, 0, modelInv, 0, projInv, 0); 
    float[] result = new float[4]; 
    float vx = viewport[0]; 
    float vy = viewport[1]; 
    float vw = viewport[2]; 
    float vh = viewport[3]; 
    float[] rhsVec = {((2*(rx-vx))/vw)-1,((2*(ry-vy))/vh)-1,2*rz-1,1}; 
    android.opengl.Matrix.multiplyMV(result, 0, combo, 0, rhsVec, 0); 
    float d = 1/result[3]; 
    float[] endResult = {result[0] * d, result[1] * d, result[2] * d}; 
    return endResult; 
} 

public float distanceToDepth(float distance) { 
    return ((1/fNear) - (1/distance))/((1/fNear) - (1/fFar)); 
} 

aşağıdaki gibidir: Kod - güncel matrisler görünüm ile MatrixGrabber - mg bir şamandıra [4] görünüm ile ({x, y, en, yükseklik})

Alınan değişkenler, gluUnProject'in alması gerekenle eşdeğerdir. Örneğin: ( ) Bu, farenin altında, uzaktaki noktaya dönecektir. Ayrıca, kameradan belirli bir mesafe ile 0-1 ... temsil ... şey arasında bir dönüşüme dönüşen bir fonksiyon ekledim. Öyleyse:

unproject(mouseX, viewport[3] - mouseY, distanceToDepth(5)); 

Bu, kameradan 5 birim fare altındaki noktayı döndürecektir. Bunu testte verilen yöntemle test ettim - yakın düzlem ve uzak uçak arasındaki mesafeyi kontrol ettim. FNear değeri 0,1 ve 100 fFar ile mesafe 99,9 olmalıdır. Anlayabildiğim kadarıyla, kameranın pozisyonuna veya oryantasyonuna bakılmaksızın, sürekli olarak 99.8977'yi buldum. Haha, bunu anlamak güzeldi. Bununla ilgili herhangi bir sorun/sorun yaşamadığınız veya global değişkenler kullanmak yerine girdileri almak için yeniden yazmamı isterseniz bana bildirin. Umarım bu birkaç kişiye yardımcı olur; Bunu düzeltmeye çalışmak için birkaç gün önce bunu merak ediyordum. Olması gerekiyordu nasıl


Hey yüzden anladım sahip, ben onlar gluUnProject uygulanmasında ne cevapsız çözdüm. Oluşan vektörün dördüncü unsuruyla bölünmeyi (hiç kimseye söylemedim ve kimseye söylemediler mi?), Bu vektörü normalleştiren bir şey mi, yoksa böyle bir şeyi mi unuttular? gluProject, matrisleri uygulamadan önce 1'e ayarlar, bu yüzden onları geri alma işlemini bitirdiğinizde 1 olması gerekir.

float[] xyzw = {0, 0, 0, 0}; 
android.opengl.GLU.gluUnProject(rx, ry, rz, mg.mModelView, 0, mg.mProjection, 0, this.viewport, 0, xyzw, 0); 
xyzw[0] /= xyzw[3]; 
xyzw[1] /= xyzw[3]; 
xyzw[2] /= xyzw[3]; 
//xyzw[3] /= xyzw[3]; 
xyzw[3] = 1; 
return xyzw; 

xyzw şimdi alakalı içermelidir: Uzun lafın kısası, [4] ve ardından şöyle, 4 teker bütün sonuçlanan koordinatları bölmek aslında gluUnProject kullanabilirsiniz, ancak bunu bir float geçmesi gerekiyor uzay koordinatları. Bu, bir araya getirdiğim ile tamamen aynı gibi görünüyor. Biraz daha hızlı olabilir; Adımlardan birini birleştirdiklerini düşünüyorum.

+0

Biraz ilerleme kaydettim. Sonuçta ** nearCoords ** alabilir ve ** ** farCoords ** (sadece Z_FAR büyüklüğüne giderim) ** yönünde ** ve iterate yineleme ben aslında seçtiğiniz ne biraz yakın. Bunun sizin için nasıl çalıştığını görün. – RedLeader

+0

Yakınlardaki Kapılar yönünde yinelemeyi denemedim, çünkü kısmen de yakınlarımın ya da farCoords'ın ilk etapta tıkladıkları yere çok fazla benzemediği görülüyordu. Ben gluUnProject çalışma (yeni bir şekilde) işe yaramadı fark ettim - gluProject aracılığıyla bazı koordinatları koştu, daha sonra sonuç aldı ve hemen sonra gluUnProject aracılığıyla çalıştı ve tamamen farklı bir şey var. Şu anda ters dönüşümü yapmaya çalışıyorum. Toplamak için lookAt kullandığınızı, ancak çizim için bir dizi dönüşüm olduğunu fark ettim. Neden? – Erhannis

+0

Sadece benim tasarımım, ve onun bir şekilde çalışması, tam olarak değil (soldan sağa, eğer sağa çok yakın olmasaydı, yakınlığı), fakat doğru düzgün bir şekilde .. – RedLeader