2010-04-21 65 views
4

我的頂點在numpy數組(dtype = float32)中交錯,如下所示:... tu,tv,nx,ny,nz,vx,vy,vz,...PyOpenGL:glVertexPointer()偏移問題

渲染時,我打電話GL *指針()這樣的(我已啓用前的陣列):

stride = (2 + 3 + 3) * 4 
glTexCoordPointer(2, GL_FLOAT, stride, self.vertArray) 
glNormalPointer(GL_FLOAT, stride, self.vertArray + 2) 
glVertexPointer(3, GL_FLOAT, stride, self.vertArray + 5) 
glDrawElements(GL_TRIANGLES, len(self.indices), GL_UNSIGNED_SHORT, self.indices) 

的結果是,沒有呈現。但是,如果我組織我的數組,使得頂點位置是第一個元素(... vx,vy,vz,tu,tv,nx,ny,nz,...),我會在渲染時得到正確的頂點位置,但紋理coords和法線不正確。

這使我相信我沒有設置指針偏移權。我應該如何設置它?我在C++中使用了幾乎完全相同的代碼,並且它可以工作。

+0

我不是PyOpenGL的用戶,但是從你的描述來看,它聽起來像+上的數組並沒有做你認爲它在那種語言中的作用。有時間檢查語言規範? – Bahbar 2010-04-21 14:43:56

+0

@Bahbar:這就是我的想法,但我一直無法找到任何有關它的信息。我搜索了很多無濟於事。 – SurvivalMachine 2010-04-21 15:41:08

回答

3

在python中,你不能做指針算術。你想要做的只適用於C/C++。

正常Python列表:

>>> array = [1, 2, 3, 4] 
>>> array 
[1, 2, 3, 4] 
>>> array + 2 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: can only concatenate list (not "int") to list 

隨着numpy的數組:

>>> import numpy 
>>> a = numpy.array([1, 2, 3]) 
>>> a + 2 
array([3, 4, 5]) 

瞭解如何既不是你想要做什麼:開始在某個位置的陣列。

我覺得你有兩種基本選擇:

  1. 不要使用交錯陣列。這確實有一個好處:當你只需要更新頂點時(比如在骨骼動畫中),你不需要更新紋理座標。
  2. 使用切片可能爲你工作。

像這樣:

>>> a = numpy.array(range(10)) 
>>> a 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
>>> a[3:] 
array([3, 4, 5, 6, 7, 8, 9]) 

用正確的步幅結合這一點,你也許可以得到它的工作。

+0

@Xavier何:謝謝,使用切片做的伎倆!但是,我不知道它的性能,所以我必須進行一些測試。 – SurvivalMachine 2010-04-26 16:48:56

+0

@SurvivalMachine:使用片的唯一缺點是它會創建一個新的副本。我現在想不出另一種方法來克服這一點。 – 2010-04-26 16:51:09

0

我回答我自己的問題,因爲我找到了一種替代方法來完成正確的結果。與其說GL *指針()的,我叫:

glInterleavedArrays(GL_T2F_N3F_V3F, stride, self.vertArray) 

我還是好奇地發現,與GL *指針有效的解決方案()。

+0

很多人推薦使用'glInterleavedArrays()'。 – 2010-04-25 05:36:48

0

根據此鏈接:http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml

步幅

指定字節連續 紋理座標集之間的偏移。 如果步幅爲0,則數組元素爲 ,理解爲緊密排列。 初始值爲0.

您確定,在您的情況下,步幅是(2 + 3 + 3)* 4嗎?

+0

我很確定。 TexCoords = 2個元素,法線= 3個元素和頂點= 3個元素。我的數組是float32,所以步長的4個字節乘以元素數量。我在C++代碼中也使用了相同的步驟,並且在那裏工作。 – SurvivalMachine 2010-04-22 07:21:36

+0

好的,那麼爲什麼在你的glNormalPointer調用中沒有「3」作爲第一個參數呢? – Wiseman 2010-04-22 08:40:41

+0

而且我還不確定,你對這個步驟感到滿意。如果你在編寫數組時使用平等的步伐,你仍然可以得到正確的值,但爲什麼要麻煩?零步可以適應(在我看來)。 – Wiseman 2010-04-22 08:43:38

3

我遇到了類似的問題,發現將偏移量轉換爲ctypes.c_void_p的確有竅門。

from ctypes import c_void_p 

t_size = self.vertArray.itemsize * 2 
n_size = self.vertArray.itemsize * 3 

t_offset = c_void_p(0) 
n_offset = c_void_p(t_size) 
v_offset = c_void_p(t_size+n_size) 

glTexCoordPointer(2, GL_FLOAT, stride, t_offset) 
glNormalPointer(GL_FLOAT, stride, n_offset) 
glVertexPointer(3, GL_FLOAT, stride, v_offset) 
glDrawElements(GL_TRIANGLES, len(self.indices), GL_UNSIGNED_SHORT, self.indices) 
+0

這個例子看起來很有希望,但我不認爲只是傳遞字節偏移量,因爲glPointer中的最後一個參數將起作用。第三個參數旨在成爲一個指向數組的指針,而不是偏移量。 – ahoffer 2011-07-25 19:12:17

+0

我今天花了很大一部分時間來處理這個問題,所以即使線程已經老化了,我仍然打電話以防萬一。 Exide是正確的,因爲,例如,http://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml表示,當glBindBuffer/glBufferData有效時,glVertexPointer將第四個參數計算爲偏移量。他的代碼片段未能顯示的是如何使用self.vertArray來實現。 – jdowdell 2013-07-18 05:46:43

+0

就像@jdowdell所說的,最後一個參數是一個偏移量。我不知道我可以添加更多關於'self.vertArray'''的信息。我只是從原來的問題中拿出來。 – Exide 2016-04-13 22:47:40