由于您已经在使用NumPy,我将给yuo一个答案,该答案使用NumPy读取二进制文件。NumPy具有一些功能,可以按不同的数据类型重新解释缓冲区数据,而这正是解释二进制文件所需要的。
二进制文件可以通过
numpy.fromfile.eg读取为字节数组。
data = numpy.fromfile(filename, dtype=np.byte)
可以将数组的某些字节解释为无符号整数(
unit32)
numpy.frombuffer。例如:
class SB6M_HEADER: def __init__(self, data): int_data = np.frombuffer(np.array(data[:16], dtype=np.byte), dtype=np.uint32) self.magic, self.size, self.num_chunks, self.flags = int_data print(self.magic, self.size, self.num_chunks, self.flags)
Porting the source pre from
sb6mfile.h
respectively
sb7object.cpp
to python and reading and “*.sbm” file:
def SB6M_FOURCC(a,b,c,d): return ( (ord(a) << 0) | (ord(b) << 8) | (ord(c) << 16) | (ord(d) << 24) )SB6M_MAGIC = SB6M_FOURCC('S','B','6','M')SB6M_CHUNK_TYPE_INDEX_DATA = SB6M_FOURCC('I','N','D','X')SB6M_CHUNK_TYPE_VERTEX_DATA = SB6M_FOURCC('V','R','T','X')SB6M_CHUNK_TYPE_VERTEX_ATTRIBS = SB6M_FOURCC('A','T','R','B')SB6M_CHUNK_TYPE_SUB_OBJECT_LIST = SB6M_FOURCC('O','L','S','T')SB6M_CHUNK_TYPE_COMMENT = SB6M_FOURCC('C','M','N','T')SB6M_CHUNK_TYPE_DATA = SB6M_FOURCC('D','A','T','A')class SB6M_HEADER: def __init__(self, data): int_data = np.frombuffer(np.array(data[:16], dtype=np.byte), dtype=np.uint32) self.magic, self.size, self.num_chunks, self.flags = int_data print(self.magic, self.size, self.num_chunks, self.flags)class SB6M_CHUNK_HEADER: def __init__(self, data, offset): int_data = np.frombuffer(np.array(data[offset:offset+8], dtype=np.byte), dtype=np.uint32) self.type, self.size = int_dataclass SB6M_CHUNK_INDEX_DATA(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+20], dtype=np.byte), dtype=np.uint32) self.index_type, self.index_count, self.index_data_offset = int_dataclass SB6M_CHUNK_VERTEX_DATA(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+20], dtype=np.byte), dtype=np.uint32) self.data_size, self.data_offset, self.total_vertices = int_dataclass SB6M_CHUNK_VERTEX_DATA(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+20], dtype=np.byte), dtype=np.uint32) self.data_size, self.data_offset, self.total_vertices = int_dataSB6M_VERTEX_ATTRIB_FLAG_NORMALIZED = 0x00000001SB6M_VERTEX_ATTRIB_FLAG_INTEGER = 0x00000002class SB6M_VERTEX_ATTRIB_DECL: def __init__(self, data, offset): self.name = ''.join([chr(n) for n in data[offset:offset+64] if n > 30]) int_data = np.frombuffer(np.array(data[offset+64:offset+84], dtype=np.byte), dtype=np.uint32) self.size, self.type, self.stride, self.flags, self.data_offset = int_dataclass SB6M_VERTEX_ATTRIB_CHUNK(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+12], dtype=np.byte), dtype=np.uint32) self.attrib_count = int_data[0] self.attrib_data = [] for i in range(self.attrib_count): self.attrib_data.append(SB6M_VERTEX_ATTRIB_DECL(data, offset+12+i*84))class SB6M_DATA_CHUNK(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+20], dtype=np.byte), dtype=np.uint32) self.encoding, self.data_offset, self.data_length = int_dataclass SB6M_SUB_OBJECT_DECL: def __init__(self, data, offset): int_data = np.frombuffer(np.array(data[offset:offset+8], dtype=np.byte), dtype=np.uint32) self.first, self.count = int_dataclass SB6M_CHUNK_SUB_OBJECT_LIST(SB6M_CHUNK_HEADER): def __init__(self, data, offset): super().__init__(data, offset) int_data = np.frombuffer(np.array(data[offset+8:offset+12], dtype=np.byte), dtype=np.uint32) self.count = int_data[0] self.sub_object = [] for i in range(self.count): self.sub_object.append(SB6M_SUB_OBJECT_DECL(data, offset+12+i*8)) def load(filename): vertex_attrib_chunk = None vertex_data_chunk = None index_data_chunk = None sub_object_chunk = None data_chunk = None try: data = numpy.fromfile(filename, dtype=np.byte) filesize = data.size header = SB6M_HEADER(data) offset = header.size for i in range(header.num_chunks): chunk = SB6M_CHUNK_HEADER(data, offset) if chunk.type == SB6M_CHUNK_TYPE_VERTEX_ATTRIBS: vertex_attrib_chunk = SB6M_VERTEX_ATTRIB_CHUNK(data, offset) elif chunk.type == SB6M_CHUNK_TYPE_VERTEX_data: vertex_data_chunk = SB6M_CHUNK_VERTEX_DATA(data, offset) elif chunk.type == SB6M_CHUNK_TYPE_INDEX_data: index_data_chunk = SB6M_CHUNK_INDEX_DATA(data, offset) elif chunk.type == SB6M_CHUNK_TYPE_SUB_OBJECT_LIST: sub_object_chunk = SB6M_CHUNK_SUB_OBJECT_LIST(data, offset) elif chunk.type == SB6M_CHUNK_TYPE_data: data_chunk = SB6M_DATA_CHUNK(data, offset) else: raise offset += chunk.size except: print("error reading file {}".format(filename))Finally the floating point vertex data can be read:
if vertex_data_chunk and vertex_attrib_chunk: start = vertex_data_chunk.data_offset end = start + vertex_data_chunk.data_size vertex_data = np.frombuffer(np.array(data[start:end], dtype=np.byte), dtype=np.float) data_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, data_buffer) glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW) vertexcount = vertex_data_chunk.total_vertices vao = glGenVertexArrays(1) glBindVertexArray(self.vao) for attrib_i, attrib in enumerate(vertex_attrib_chunk.attrib_data): if attrib.name=='position' or attrib.name=='map1': glVertexAttribPointer(attrib_i, attrib.size, attrib.type, GL_TRUE if (attrib.flags & SB6M_VERTEX_ATTRIB_FLAG_NORMALIZED) != 0 else GL_FALSE, attrib.stride, ctypes.c_void_p(int(attrib.data_offset))) glEnableVertexAttribArray(attrib_i)
Finally draw the mesh:
glBindVertexArray(vao)glDrawArrays(GL_TRIANGLES, 0, vertexcount)



