2010-04-21 70 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