Question

My vertices are interleaved in a numpy array (dtype = float32) like this: ... tu, tv, nx, ny, nz, vx, vy, vz, ...

When rendering, I'm calling gl*Pointer() like this (I have enabled the arrays before):

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 )

The result is that nothing renders. However, if I organize my array so that the vertex position is the first element ( ... vx, vy, vz, tu, tv, nx, ny, nz, ... ) I get correct positions for vertices while rendering but texture coords and normals aren't rendered correctly.

This leads me to believe that I'm not setting the pointer offset right. How should I set it? I'm using almost the exact same code in my other app in C++ and it works.

Was it helpful?

Solution

In python, you can't do pointer arithmetic. What you're trying to do only works for C/C++.

With normal Python list:

>>> 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

With numpy arrays:

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

See how neither does what you want: starting the array at a certain position.

I think you have basically two options:

  1. Don't use interleaved arrays. This does have one advantage: when you only need to update the vertices (like in bone animations), you don't need to update the texture coordinates.
  2. Using slices might work for you.

Like this:

>>> 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])

Combine this with a correct stride, you can probably get it to work.

OTHER TIPS

I ran into a similar problem and found that casting the offset to ctypes.c_void_p did the trick.

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 )

I'm answering my own question, because I found an alternative way to accomplish the correct result. Instead of calling gl*Pointer(), I called:

glInterleavedArrays( GL_T2F_N3F_V3F, stride, self.vertArray )

I'm still curious to find a solution that works with gl*Pointer().

According to this link: http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml

stride

Specifies the byte offset between consecutive texture coordinate sets. If stride is 0, the array elements are understood to be tightly packed. The initial value is 0.

Are you sure, that in your case stride is (2 + 3 + 3) * 4 ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top