views:

187

answers:

3

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.

A: 

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().

SurvivalMachine
A lot of people recommend against `glInterleavedArrays()`.
Xavier Ho
A: 

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 ?

Wiseman
I'm quite sure. TexCoords = 2 elements, Normals = 3 elements and Vertices = 3 elements. My array is float32, so the stride's 4 bytes multiplied by the # of elements. I'm using the same stride also in my C++ code and it works there.
SurvivalMachine
Ok, then why there is no "3" as a first param in your glNormalPointer call?
Wiseman
And I'm still not sure, that you sholuld this stride. If you are using equal stride while composing array, you still can get right values, but why bother? Zero stride could fit as well (in my opinion).
Wiseman
Zero stride would definitely not work for an interleaved array.
Xavier Ho
A: 

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.

Xavier Ho
@Xavier Ho: Thanks, using slices did the trick! However, I don't know about its performance, so I must run some tests.
SurvivalMachine
@SurvivalMachine: The only downside of using slices is that it creates a new copy of your list. I can't think of another way to overcome that at the moment.
Xavier Ho