2010-04-21 5 views
4

Мои вершины чередуются в Numpy массиве (DTYPE = float32), как это: ... вт, телевизор, пх, пу, пг, Vx, Vy, уг, ...PyOpenGL: glVertexPointer() смещение проблема

При визуализации я звоню Г.Л. * Pointer() как это (я включен массивы до):

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, ...) Я получаю правильные позиции для вершин при рендеринге, но текстуре коорды и нормали не отображаются правильно.

Это заставляет меня думать, что я не устанавливаю смещение указателя вправо. Как мне его установить? Я использую почти тот же код в другом приложении на C++, и он работает.

+0

Я не пользователь PyOpenGL, но из вашего описания это похоже на массивы + на массивах, которые не делают то, что вы думаете на этом языке. Время проверить спецификацию языка? – Bahbar

+0

@ Бахбар: Это то, что я думал, но я не смог найти никакой информации об этом. Я много гугл безрезультатно. – SurvivalMachine

ответ

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 Ho: Спасибо, используя кусочки сделали трюк! Однако я не знаю о его производительности, поэтому я должен выполнить некоторые тесты. – SurvivalMachine

+0

@SurvivalMachine: Единственным недостатком использования фрагментов является то, что он создает новую копию вашего списка. Я не могу думать о другом способе преодолеть это на данный момент. –

0

Я отвечаю на свой вопрос, потому что нашел альтернативный способ добиться правильного результата. Вместо вызова Г.Л. * Указатель(), я назвал:

glInterleavedArrays(GL_T2F_N3F_V3F, stride, self.vertArray) 

Я все еще интересно, чтобы найти решение, которое работает с гл * Pointer().

+0

Многие люди рекомендуют против 'glInterleavedArrays()'. –

0

По этой ссылке: http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml

шаг

Определяет смещение байта между последовательными текстурными координатами множествами. Если шаг равен 0, элементы массива понимаются как плотно упакованные. Начальное значение равно 0.

Вы уверены, что в вашем случае шаг (2 + 3 + 3) * 4?

+0

Я совершенно уверен. TexCoords = 2 элемента, Normals = 3 элемента и Vertices = 3 элемента. Мой массив - float32, поэтому 4 байта шага умножаются на # элементов. Я использую тот же самый шаг и в своем коде на C++, и он работает там. – SurvivalMachine

+0

Итак, почему нет «3» в качестве первого параметра в вызове glNormalPointer? – Wiseman

+0

И я до сих пор не уверен, что вы сошли с ума. Если вы используете равный шаг при составлении массива, вы все равно можете получить правильные значения, но зачем беспокоиться? Нулевой шаг тоже мог поместиться (на мой взгляд). – Wiseman

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

+0

Я потратил хороший кусок сегодняшнего дня на эту проблему, поэтому, несмотря на то, что поток старый, я нахожусь в том случае, если он помогает кому-то другому. Exide правильно, потому что, например, http://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml говорит, что glVertexPointer оценивает четвертый аргумент как смещение, когда glBindBuffer/glBufferData действует. Невозможно показать его фрагмент кода, как это сделать с помощью self.vertArray. – jdowdell

+0

Как и @jdowdell, последним аргументом является смещение. Я не уверен, что еще могу добавить в отношении '' 'self.vertArray'''. Я просто взял его из оригинального вопроса. – Exide

Смежные вопросы