Anonymous
PyOpenGL, похоже, не работает с тримешем .obj через glDrawElementsInstanced
Сообщение
Anonymous » 12 дек 2025, 04:01
У меня есть файлы .obj, которые я загружаю через tripesh.load, а затем подготавливаю данные вершин и индексы. Однако PyOpenGL, похоже, неправильно рисует сетку через glDrawElementsInstanced (часть «Instanced» работает нормально).
Загрузчик сетки из файла
Код: Выделить всё
def _load_mesh_from_file(self, path):
mesh = trimesh.load(path, force="mesh")
trimesh.repair.fill_holes(mesh)
trimesh.repair.fix_winding(mesh)
# vertices_pos = data[:, 0:3]
# vertices_uv = data[:, 3:5] # texcoord
# vertices_normal = data[:, 5:8] # normal
# vertices_tangent = data[:, 8:11] # tangent
# vertices_bitangent = data[:, 11:14] # bitangent
faces = mesh.faces
vertex_pos = mesh.vertices
vertex_uv = mesh.visual.uv
vertex_normal = mesh.vertex_normals
vertex_tangent, vertex_bitangent = self._load_tangent_bitangent(
vertex_pos, vertex_uv, faces
)
vertex_data = []
for i in range(len(vertex_pos)):
vertex_data.extend(
[
*vertex_pos[i],
*vertex_uv[i],
*vertex_normal[i],
*vertex_tangent[i],
*vertex_bitangent[i],
]
)
return np.ascontiguousarray(
vertex_data, dtype=np.float32
), np.ascontiguousarray(
faces, dtype=np.uint32
) # this is what makes up mesh_data
Экземпляр сетки
Код: Выделить всё
def __init__(
self,
mesh_data: list | tuple,
name: str = "",
position: list | np.ndarray = [0, 0, 0],
eulers: list | np.ndarray = [0, 0, 0],
scale: list | np.ndarray = [1, 1, 1],
):
self.objects: list = []
self.position = np.array(position, dtype=np.float32)
self.eulers = np.array(eulers, dtype=np.float32)
self.scale = np.array(scale, dtype=np.float32)
self.name = name
self.max_instances = 1000
self.mesh_data = mesh_data
vertex_data = mesh_data[0]
indices = mesh_data[1]
self.vertex_data = np.ascontiguousarray(vertex_data, dtype=np.float32)
self.indices_data = np.ascontiguousarray(indices, dtype=np.uint32)
self.vertex_count = vertex_data.shape[0]
self.index_count = len(indices)
stride = 14 * 4
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)
vertex_buffer = np.array(self.vertex_data, dtype=np.float32).reshape(
-1, 14
)
self.vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(
GL_ARRAY_BUFFER, vertex_buffer.nbytes, vertex_buffer, GL_STATIC_DRAW
)
index_buffer = np.array(self.indices_data, dtype=np.uint32)
self.ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
index_buffer.nbytes,
index_buffer,
GL_STATIC_DRAW,
)
# Posizione
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(0))
# UV
glEnableVertexAttribArray(1)
glVertexAttribPointer(
1, 2, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(12)
)
# Normale
glEnableVertexAttribArray(2)
glVertexAttribPointer(
2, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(20)
)
# Tangente
glEnableVertexAttribArray(3)
glVertexAttribPointer(
3, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(32)
)
# Bitangente
glEnableVertexAttribArray(4)
glVertexAttribPointer(
4, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(44)
)
self._gpu_indices = self.indices_data
self._gpu_vertices = self.vertex_data
self.max_instances = getattr(self, "max_instances", 1000)
self.instance_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.instance_vbo)
glBufferData(
GL_ARRAY_BUFFER, self.max_instances * 16 * 4, None, GL_DYNAMIC_DRAW
)
for i in range(4):
glEnableVertexAttribArray(5 + i)
glVertexAttribPointer(
5 + i, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(i * 16)
)
glVertexAttribDivisor(5 + i, 1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
Вызов рисования
Код: Выделить всё
def draw(self, instance_count):
if instance_count == 0:
return
self._bind_vao()
self.shader.use()
if engine_config.SHOW_WIRE_FRAME:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glDrawElementsInstanced(
GL_TRIANGLES, self.index_count, GL_UNSIGNED_INT, None, instance_count
)
# glDrawArraysInstanced(
# GL_TRIANGLES,
# 0,
# self.vertex_count,
# instance_count
# )
if engine_config.SHOW_WIRE_FRAME:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
glBindVertexArray(0)
# glDrawArraysInstanced( GL_LINE_STRIP, 0, self.vertex_count, instance_count )
Каркас куба:
Куб:
Подробнее здесь:
https://stackoverflow.com/questions/798 ... sinstanced
1765501303
Anonymous
У меня есть файлы .obj, которые я загружаю через tripesh.load, а затем подготавливаю данные вершин и индексы. Однако PyOpenGL, похоже, неправильно рисует сетку через glDrawElementsInstanced (часть «Instanced» работает нормально). [b]Загрузчик сетки из файла[/b] [code]def _load_mesh_from_file(self, path): mesh = trimesh.load(path, force="mesh") trimesh.repair.fill_holes(mesh) trimesh.repair.fix_winding(mesh) # vertices_pos = data[:, 0:3] # vertices_uv = data[:, 3:5] # texcoord # vertices_normal = data[:, 5:8] # normal # vertices_tangent = data[:, 8:11] # tangent # vertices_bitangent = data[:, 11:14] # bitangent faces = mesh.faces vertex_pos = mesh.vertices vertex_uv = mesh.visual.uv vertex_normal = mesh.vertex_normals vertex_tangent, vertex_bitangent = self._load_tangent_bitangent( vertex_pos, vertex_uv, faces ) vertex_data = [] for i in range(len(vertex_pos)): vertex_data.extend( [ *vertex_pos[i], *vertex_uv[i], *vertex_normal[i], *vertex_tangent[i], *vertex_bitangent[i], ] ) return np.ascontiguousarray( vertex_data, dtype=np.float32 ), np.ascontiguousarray( faces, dtype=np.uint32 ) # this is what makes up mesh_data [/code] [b]Экземпляр сетки[/b] [code]def __init__( self, mesh_data: list | tuple, name: str = "", position: list | np.ndarray = [0, 0, 0], eulers: list | np.ndarray = [0, 0, 0], scale: list | np.ndarray = [1, 1, 1], ): self.objects: list = [] self.position = np.array(position, dtype=np.float32) self.eulers = np.array(eulers, dtype=np.float32) self.scale = np.array(scale, dtype=np.float32) self.name = name self.max_instances = 1000 self.mesh_data = mesh_data vertex_data = mesh_data[0] indices = mesh_data[1] self.vertex_data = np.ascontiguousarray(vertex_data, dtype=np.float32) self.indices_data = np.ascontiguousarray(indices, dtype=np.uint32) self.vertex_count = vertex_data.shape[0] self.index_count = len(indices) stride = 14 * 4 self.vao = glGenVertexArrays(1) glBindVertexArray(self.vao) vertex_buffer = np.array(self.vertex_data, dtype=np.float32).reshape( -1, 14 ) self.vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vbo) glBufferData( GL_ARRAY_BUFFER, vertex_buffer.nbytes, vertex_buffer, GL_STATIC_DRAW ) index_buffer = np.array(self.indices_data, dtype=np.uint32) self.ebo = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo) glBufferData( GL_ELEMENT_ARRAY_BUFFER, index_buffer.nbytes, index_buffer, GL_STATIC_DRAW, ) # Posizione glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(0)) # UV glEnableVertexAttribArray(1) glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(12) ) # Normale glEnableVertexAttribArray(2) glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(20) ) # Tangente glEnableVertexAttribArray(3) glVertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(32) ) # Bitangente glEnableVertexAttribArray(4) glVertexAttribPointer( 4, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(44) ) self._gpu_indices = self.indices_data self._gpu_vertices = self.vertex_data self.max_instances = getattr(self, "max_instances", 1000) self.instance_vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.instance_vbo) glBufferData( GL_ARRAY_BUFFER, self.max_instances * 16 * 4, None, GL_DYNAMIC_DRAW ) for i in range(4): glEnableVertexAttribArray(5 + i) glVertexAttribPointer( 5 + i, 4, GL_FLOAT, GL_FALSE, 64, ctypes.c_void_p(i * 16) ) glVertexAttribDivisor(5 + i, 1) glBindBuffer(GL_ARRAY_BUFFER, 0) glBindVertexArray(0) [/code] [b]Вызов рисования[/b] [code] def draw(self, instance_count): if instance_count == 0: return self._bind_vao() self.shader.use() if engine_config.SHOW_WIRE_FRAME: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glDrawElementsInstanced( GL_TRIANGLES, self.index_count, GL_UNSIGNED_INT, None, instance_count ) # glDrawArraysInstanced( # GL_TRIANGLES, # 0, # self.vertex_count, # instance_count # ) if engine_config.SHOW_WIRE_FRAME: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glBindVertexArray(0) # glDrawArraysInstanced( GL_LINE_STRIP, 0, self.vertex_count, instance_count ) [/code] Каркас куба: [img]https://i.sstatic.net/g5lfUrIz.png[/img] Куб: [img]https://i.sstatic.net/AylBeS8J.png[/img] Подробнее здесь: [url]https://stackoverflow.com/questions/79844398/pyopengl-seems-not-to-work-with-trimesh-obj-through-gldrawelementsinstanced[/url]