2014-06-19 59 views
1

一般來說,我的問題是如何爲vbo提供2個索引。一個用於頂點,一個用於法線? 我的下一個OBJ文件:Vbo - 用obj文件繪製法線

mtllib cube.mtl 

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 
vn 0.000000 -1.000000 0.000000 
vn 0.000000 1.000000 0.000000 
vn 1.000000 0.000000 0.000000 
vn -0.000000 -0.000000 1.000000 
vn -1.000000 -0.000000 -0.000000 
vn 0.000000 0.000000 -1.000000 

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

正如你可以看到有8個頂點和6個法線。在面線上,文件通過索引將每個頂點連接到下一個頂點,並通過不同的索引連接法線。

我想用vbo與多維數據集模型繪製。我寫了以下代碼:

float vertex[] = {1, -1, -1, 
       1, -1, 1, 
      -1, -1, 1, 
      -1, -1, -1, 
       1, 1, -1, 
       1, 1, 1, 
      -1, 1, 1, 
       -1, 1, -1}; 
float normals[] = {0, -1, 0, 
        0, 1, 0, 
        1, 0, 0, 
        0, 0, 1, 
        -1, 0, 0, 
        0, 0, -1}; 
int index[] = {0, 1, 2, 3, 
       4, 7, 6, 5, 
       0, 4, 5, 1, 
       1, 5, 6, 2, 
       2, 6, 7, 3, 
       4, 0, 3, 8}; 




GLuint buffer, ind; 
int offset = 0; 

void vboInit() 
{ 
    glGenBuffers(1, &buffer); 
    glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) + sizeof(normals), 0, GL_STATIC_DRAW); 
    glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(vertex), vertex);  offset+= sizeof(vertex); 
    glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(normals), normals);  offset+= sizeof(normals); 


    glGenBuffers(1, &ind); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW); 
} 

void vboDraw() 
{ 
    glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind); 
    glNormalPointer(GL_FLOAT, 0, (GLvoid*)(sizeof(vertex))); 
    glVertexPointer(3, GL_FLOAT, 0, 0); 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_NORMAL_ARRAY); 
    for (int i = 0; i < 6; i++) 
     glDrawElements(GL_TRIANGLE_FAN, 4 + i*4, GL_UNSIGNED_INT, (GLvoid*)(i*4)); 
    glDisableClientState(GL_NORMAL_ARRAY); 
    glDisableClientState(GL_VERTEX_ARRAY); 


    glBindBuffer(GL_ARRAY_BUFFER, NULL);   
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);  
} 

此代碼使用法線頂點的索引。因此法線加載不好,我需要與法線不同的指數。問題是如何爲vbo提供2個索引。一個用於頂點,一個用於法線?

+1

不知道你的問題應該被標記爲一個確切的重複,但我回答以前非常類似的問題。這兩個答案應該涵蓋你在找什麼:http://stackoverflow.com/questions/23710829/why-is-my-obj-parser-rendering-meshes-like-this/23713424#23713424,http:// stackoverflow.com/questions/23349080/opengl-index-buffers-difficulties/23356738#23356738。 –

回答

0

簡而言之,你不能。但是如果你想要長一個:

DrawElements需要索引頂點數組。頂點是而不是一個位置;它是一次組裝所有屬性。當您通過索引獲取頂點時,您必須從每個屬性數組的相同索引中獲取它。索引的好處在於它們支持使用TNL後緩存(但是,緩存的使用取決於實際的索引值)並減少內存使用量。

如果您的數據以類似於OBJ的佈局保存,其中屬性數組以獨立方式索引,則必須將數組轉換爲更友好的表示形式。簡單的做法是:

  • 分配大數組[s],因此它可以保存所有頂點數據,即使沒有索引。
  • 對於每個三角形,使用獨立索引將數據提取到新數組。因此,您的頂點現在沒有獨立的屬性索引 - 但它們根本沒有索引!你已經可以繪製 - 用DrawArrays()。
  • 如果你想索引,現在你可以重新創建它們。刪除新頂點數組中的重複項(重複項的整個頂點等於,不僅位置),並且每個三角形都找到新數組中的頂點索引。
+0

重複是什麼意思? – DarkStorm97

+1

如果特定頂點的所有屬性與其他頂點相匹配,則其中一個頂點是重複的,並且可能會被刪除。 – keltar

+0

雖然建議您使用方法,但通過比較實際的頂點數據來移除重複內容似乎非常低效。看到這裏更有效的方法:http://stackoverflow.com/questions/23349080/opengl-index-buffers-difficulties/23356738#23356738。 –