2014-12-30 84 views
0

在我的第一個Android OpenGL應用程序中,我想渲染一個帶紋理的簡單立方體到屏幕。我從obj文件加載我的對象,如果我用一種顏色渲染它,它的效果很好,但是使用紋理我有一些問題。我放棄了我的代碼,並查看所有數組,並發現所有文件都可以正常讀取。這裏是我的OBJ文件:告訴OpenGL三角形的正確紋理座標

v 1.000000 -1.000000 -1.000000 
v 1.000000 -1.000000 1.000000 
v -1.000000 -1.000000 1.000000 
v -1.000000 -1.000000 -1.000000 
v 1.000000 1.000000 -0.999999 
v 0.999999 1.000000 1.000001 
v -1.000000 1.000000 1.000000 
v -1.000000 1.000000 -1.000000 

vt -1.918677 2.918677 
vt -1.918677 -1.918677 
vt 2.918677 -1.918677 
vt 2.918677 2.918677 

f 2/1 3/2 4/3 
f 8/1 7/2 6/3 
f 1/4 5/1 6/2 
f 2/4 6/1 7/2 
f 7/1 8/2 4/3 
f 1/1 4/2 8/3 
f 1/4 2/1 4/3 
f 5/4 8/1 6/3 
f 2/3 1/4 6/2 
f 3/3 2/4 7/2 
f 3/4 7/1 4/3 
f 5/4 1/1 8/3 

要在屏幕上繪製的對象我有這些陣列(後來作爲緩衝區),這些OpenGL的方法:

float vertices[] = {1f, -1f, -1f, 1f, ... , -1f, 1f, -1f }; 
short order[] = { 1, 2, 3, 7, ... , 4, 0, 7 }; // f o/t | o - 1 
float textures[] = { -1.918677, 2.918677, ... , 2.918677 2.918677 }; 

Matrix.multiplyMM(mvpMatrix, 0, vpMatrix, 0, modelMatrix, 0); 
GLES20.glUniformMatrix4fv(shaderMatrix, 1, false, mvpMatrix, 0); 

GLES20.glEnableVertexAttribArray(shaderPosition); 
GLES20.glVertexAttribPointer(shaderPosition, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); 

GLES20.glEnableVertexAttribArray(shaderTexCoordinate); 
GLES20.glVertexAttribPointer(shaderTexCoordinate, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); 

GLES20.glDrawElements(GLES20.GL_TRIANGLES, orderBuffer.capacity(), GLES20.GL_UNSIGNED_SHORT, orderBuffer); 
GLES20.glDisableVertexAttribArray(shaderPosition); 

但是,這並不工作 - 質地沒有正確顯示。我推測OpenGL不知道使用女巫紋理座標繪製哪個三角形。那麼我怎麼能告訴這個OpenGL?我是否必須爲具有相同尺寸的頂點的紋理座標創建一個數組/緩衝區,以便OpenGL使用第一個頂點渲染三角形以及此三角形的前三個紋理拾取物?或者我該怎麼做呢?

所以總結一下:我可以設置類似drawOrder函數的東西,但是對於textureCoordinates?

+0

查看http://stackoverflow.com/a/23356738和http://stackoverflow.com/a/23713424查找描述如何處理這個問題的答案。 –

+0

請在這裏看到我自己的答案。我認爲我已經實現了僞代碼,現在紋理看起來很棒,但是現在多維數據集本身並不是完美的。頂點有什麼問題嗎? – Cilenco

+0

這段代碼看起來很合理。我會使用一個簡單的例子,如多維數據集,並在調試器中逐步完成。應該相當明顯地發現問題出在哪裏。 –

回答

1

OpenGL認爲單個頂點是描述該頂點的每個屬性的組合。所以,就你而言,由位置和紋理座標組成的單個單元是一個頂點。它們是五維的。

的線像:

f 2/1 3/2 4/3 

描述了具有三個頂點的三角形。頂點的座標分別爲:

(1.000000 -1.000000 1.000000, -1.918677 2.918677) 
(-1.000000 -1.000000 1.000000, -1.918677 -1.918677) 
(-1.000000 -1.000000 -1.000000, 2.918677 -1.918677) 

你可能想加載由:

  1. 創建一個包含每個v陣列;
  2. 創建一個包含每個vt的數組;
  3. 創建一個從(v, vt)索引的哈希映射;
  4. 爲每個頂點稱爲由f,請參考散列映射爲一個索引:
    • 如果存在,則該索引添加到排序緩衝器;
    • 否則查找適當的值是vvt並把它們添加到您的vertexBuffertextureBuffer陣列,存儲你只是寫給到這兩個哈希映射鍵(v, vt)和訂單緩衝位置的索引。

既然你正在繪製一個立方體,很可能你會用24個頂點結束了 - 你vertexBuffer陣列將是24個* 3個標量長時間,你textureBuffer陣列將是24個* 2標量長。您的瞬態哈希映射將包含24個項目,映射到從0到23的整數。

+0

我不真正理解你在做第4步。'ShaderPosition'和'shaderTexCoordinate'不是數組 - 它們只是來自着色器的變化。如果我創建一個HashMap,我怎樣才能將它傳遞給OpenGL框架? – Cilenco

+0

對不起,不好的複製和粘貼。應該修復。你的數組當然是'vertexBuffer'和'textureBuffer'。 – Tommy

+0

謝謝你。我認爲這對我有很大幫助 – Cilenco

0

我的代碼用於從obj文件加載對象。最後,我將verticestexturesdrawings ArrayLists轉換爲數組和緩衝區。

編輯:對於所有如何尋找obj裝載機。這裏的代碼很好用。請確保啓用depth buffer。那是我的問題。否則,三角形會在另一個前面繪製,看起來不像一個立方體。感謝大家對此代碼的幫助。

while((line = bufferedReader.readLine()) != null) 
{ 
    lineCounter += 1; line.trim(); 
    if(line.length() <= 1) continue; 

    StringTokenizer tok = new StringTokenizer(line, " "); 
    String cmp = tok.nextToken(); 

    if(cmp.equals("v")) 
    { // Read out the vertices 
     all_vertices.add( Float.valueOf(tok.nextToken()) ); 
     all_vertices.add( Float.valueOf(tok.nextToken()) ); 
     all_vertices.add( Float.valueOf(tok.nextToken()) ); 
    } 
    else if(cmp.equals("vt")) 
    { // Read out the texture 
     all_textures.add( Float.valueOf(tok.nextToken()) ); 
     all_textures.add( Float.valueOf(tok.nextToken()) ); 
    } 
    else if(cmp.equals("f") || cmp.equals("fo")) 
    { 
     while(tok.hasMoreTokens()) 
     { 
      String indices = tok.nextToken().trim(); 
      String[] variables = indices.split("/"); 

      if(map.containsKey(indices)) drawings.add(map.get(indices)); 
      else 
      { 
       short vertexIndex = (short) (vertices.size()/3); 
       map.put(indices, vertexIndex); drawings.add(vertexIndex); 
       Log.d("ME", indices + "|" + vertexIndex); 

       int verNumber = Integer.valueOf(variables[0]) - 1; 
       vertices.add(all_vertices.get(3 * verNumber + 0)); 
       vertices.add(all_vertices.get(3 * verNumber + 1)); 
       vertices.add(all_vertices.get(3 * verNumber + 2)); 

       int texNumber = Integer.valueOf(variables[1]) - 1; 
       textures.add(all_textures.get(2 * texNumber + 0)); 
       textures.add(all_textures.get(2 * texNumber + 1)); 
      } 
     } 
    } 
} 

在這裏,你也有一小片的代碼的ArrayLists轉換成數組,你可以再放入特定的緩衝區。它非常高效,位於複雜性n。玩得開心:

float vertices[] = new float[vert.size()]; 
short drawings[] = new short[draw.size()]; 
float textures[] = new float[texs.size()]; 

int maxVD = Math.max(vert.size(), draw.size()); 
int maxVNT = Math.max(maxVD, texs.size()); 
Log.d("ME", "" + maxVNT); 

for(int i=0; i < maxVNT; i++) 
{ 
    int vi = Math.min(i, vertices.length - 1); 
    vertices[vi] = vert.get(vi); 

    int di = Math.min(i, drawings.length - 1); 
    drawings[di] = draw.get(di); 

    int ti = Math.min(i, textures.length - 1); 
    textures[ti] = texs.get(ti); 
}