opengl es 射線拾取

2021-06-02 03:10:38 字數 2831 閱讀 2148

後來只好自己一點一點蒐集資料,但是無奈不知道為什麼網上這個內容有價值的特別特別少,但是好在這個過程中熟悉了android除錯過程,又找到了其他一些有用的東西,就寫了第乙個帖子:

android平台下opengl學習例程:

在第乙個帖子發完之後,很多開發者留了言,給了意見,我發現有些問題是大家都碰到的,討論之後,問題的結果以及具體的方案漸漸浮出水面。下面就對opengl es實現射線拾取方法做一下總結。

opengl2.0的拾取使用的不是射線拾取,但是現在opengles貌似只能使用射線拾取。

做這個的時候碰到兩個問題:

1、無法得到模型檢視和投影矩陣,因為opengles本身不提供opengl2.0裡面獲得矩陣的介面;

2、gluunproject方法出錯。

當時考慮第乙個問題有三個解決方法:

事實上自己使用第二個和第三個方法的時候都遇到更頭疼的問題,比如第二個方法得到的引數跟自己想想的差距比較大,沒有完全弄明白意思;第三個方法總是報錯,應該是自己除錯經驗不足造成的;於是最終使用了第乙個方法,即自己設定自己的矩陣,重寫各種矩陣操作,這個方法雖然麻煩,但是對於不是特別熟練的opengl開發者有乙個好處,就是你能對你使用的矩陣了解非常透徹,不至於自己把自己弄糊塗了。

//3d模型檢視矩陣,投影矩陣,視口等 

final float projm = new float[16];

final float rotm = new float[16];

final float modelm = new float[16];

int view;

其中的矩陣操作可以使用gl.glmultmatrixf()方法,例如旋轉操作可以重寫為:

public void rotatematrix(float rot, float x, float y, float z, gl10 gl) 

使用自己的矩陣還得注意設定投影矩陣跟顯示的一樣:

public void onsu***cechanged(gl10 gl, int width, int height) 

float size = 0.05f;

view = new int;

float ratio = (float) width / (float) height;

gl.glviewport(0, 0, width, height);

gl.glmatrixmode(gl10.gl_projection);

gl.glloadidentity();

gl.glfrustumf(-size, size, -size / ratio, size / ratio, 0.1f, 100f);

gl.glenable(gl10.gl_depth_test);

//設定投影矩陣和檢視中的投影矩陣一樣

matrix.setidentitym(projm, 0);

matrix.frustumm(projm, 0, -size, size, -size / ratio, size / ratio, 0.1f, 100f);

}

這樣在繪製的時候就可以使用自己的模型矩陣了:

gl.glmatrixmode(gl10.gl_modelview); 

gl.glloadidentity();

matrix.setidentitym(modelm, 0);

gl.glmultmatrixf(modelm, 0);

好,通過上面的方法,我們就不用使用opengl es給出的方法獲得模型檢視以及投影矩陣了,只要用自己的變數就行。第二個問題來了,如何使用glu.gluunproject方法。

這個問題一度糾結了自己很長時間,主要是google沒有給出方法中各個引數的意義,看方法很容易理解,glu.gluunproject(touchx, (viewport[3] - touchy - 1.0f), 0.0f, mv, 0,  prj, 0, viewport, 0,  ret1, 0);前兩個引數是轉換成opengl座標的觸控點,第三個是觸控點的z平面的值,注意,並不是得到結果的z座標的值,這個值是你平截頭體的far的相對於視點的位置,只有模型檢視矩陣和投影矩陣恰好重合的時候才是z座標的值,mv是模型檢視矩陣,下乙個是其偏移量,prj是投影矩陣,同樣後面跟著乙個偏移量,viewport是視口,後面的0也是偏移量,問題是倒數第二個引數,ret1!

按照opengl es裡面的定義,這個ret1應該是乙個3元素向量,即反投影的(x, y, z)的值(c#中即是這樣),然而事實卻並非如此。ret1竟然是乙個4元素的陣列,而不是3元素!而且其中的結果也不能直接拿來用,那麼反投影的值在哪呢?自己測試了各種資料,終於找到了問題。

ret1[3]這個數是個比例,所以最終反投影的結果應該是(ret1[0]/ret1[3], ret1[1]/ret1[3], ret1[2]/ret1[3]),這樣,想獲得射線的**就可以寫成如下的樣子:

public void unprojectandgetray(float x, float y) 

raystart = new vec3(r1[0], r1[1], r1[2]);

rayend = new vec3(r2[0], r2[1], r2[2]);

}

其中raystart是射線的起點,rayend是射線的終點,都是三維向量。

後面的射線演算法應該大家在網上就很容易找到了,如何判斷三角形跟射線相交等等,牽扯到數學上面的演算法,這裡就不做累述了。

OPENGL ES 物件的拾取

使用者問題的說明 響應滑鼠操作,其當中有乙個非常重要的知識 使用滑鼠點取,達到對三維模型物件的捕捉。物件的拾取,這是3d當中的乙個專業術語。也就是在二維螢幕當中選擇三維物件。我們要使用之前的業務邏輯來進行的處理。此拾取的功能,其與初始化模組是沒有關係的,與顯示模組也是沒有關係的。其只與使用者操作模組...

osgearth向量拾取

向量拾取是最近才做的功能,以前一直認為這個功能可能會很麻煩,原因呢 osgearth裡 估計所有的gis球中 是將向量光柵化成紋理貼到球上的,怎麼拾取一張上的一條線呢 osgearth的自帶例子裡沒有找到向量拾取的例子 最終這個功能畢竟是做出來了,這裡把自己的探索過程梳理一下.首先去google上搜...

vr發射拾取

啊void fixedupdate if device.gettouchdown steamvr controller.buttonmask.trigger if device.gettouchup steamvr controller.buttonmask.trigger if device.ge...