96 lines
3.6 KiB
Python
96 lines
3.6 KiB
Python
from collections import defaultdict
|
|
from itertools import chain, islice
|
|
|
|
from collada import parse
|
|
from collada import types
|
|
|
|
from prettyprinter import pprint, install_extras
|
|
install_extras(include=["dataclasses"])
|
|
|
|
def resolve_input_source(collada, source_uri):
|
|
return element
|
|
|
|
def find_semantics(inputs, semantic):
|
|
return [i for i in inputs if i.semantic == semantic]
|
|
|
|
def mesh_vertex_buffer(collada, mesh):
|
|
semantic_names = ["NORMAL", "TEXCOORD"]
|
|
|
|
assert len(mesh.primitive_elements) == 1
|
|
triangles, = mesh.primitive_elements
|
|
assert type(triangles) is types.Triangles
|
|
|
|
vertex_input, = find_semantics(triangles.inputs, "VERTEX")
|
|
vertices = collada.lookup(vertex_input.source, types.Vertices)
|
|
position_input, = find_semantics(vertices.inputs, "POSITION")
|
|
position_source = collada.lookup(position_input.source, types.SourceCore)
|
|
assert type(position_source.array_element) is types.FloatArray
|
|
|
|
by_offset = defaultdict(list)
|
|
by_offset[vertex_input.offset].append((vertex_input, position_source))
|
|
|
|
for semantic_name in semantic_names:
|
|
for input in find_semantics(triangles.inputs, semantic_name):
|
|
source = collada.lookup(input.source, types.SourceCore)
|
|
assert type(source.array_element) is types.FloatArray
|
|
by_offset[input.offset].append((input, source))
|
|
|
|
max_offset = max(i.offset for i in triangles.inputs)
|
|
p_stride = max_offset + 1
|
|
assert len(triangles.p) == triangles.count * 3 * p_stride
|
|
|
|
######################################################################
|
|
# generate the index/vertex buffer
|
|
######################################################################
|
|
vertex_buffer_stride = sum(
|
|
source.technique_common.accessor.stride
|
|
for input, source in chain.from_iterable(by_offset.values())
|
|
)
|
|
index_table = {}
|
|
next_output_index = 0
|
|
index_buffer = []
|
|
vertex_buffer = []
|
|
|
|
used_offsets = [offset for offset in range(p_stride) if offset in by_offset]
|
|
|
|
for vertex_ix in range(triangles.count * 3):
|
|
index_table_key = tuple(triangles.p[vertex_ix * p_stride + offset] for offset in used_offsets)
|
|
print(index_table_key)
|
|
if index_table_key in index_table:
|
|
index_buffer.append(index_table[index_table_key])
|
|
continue
|
|
|
|
index_table[index_table_key] = next_output_index
|
|
index_buffer.append(next_output_index)
|
|
next_output_index += 1
|
|
|
|
# emit vertex attributes for new output index in vertex buffer
|
|
for offset in used_offsets:
|
|
p_index = triangles.p[vertex_ix * p_stride + offset]
|
|
for input, source in by_offset[offset]:
|
|
print(input.semantic, end=" ")
|
|
source_stride = source.technique_common.accessor.stride
|
|
source_index = p_index * source_stride
|
|
array_slice = source.array_element.floats[source_index:source_index+source_stride]
|
|
print(array_slice, end=" ")
|
|
vertex_buffer.extend(array_slice)
|
|
print()
|
|
|
|
print("{")
|
|
for i in range(triangles.count):
|
|
print(", ".join(str(index_buffer[i * 3 + j]) for j in range(3)), end=",\n")
|
|
print("}")
|
|
print("{")
|
|
for i in range(len(index_table)):
|
|
print(", ".join(str(vertex_buffer[i * vertex_buffer_stride + j])
|
|
for j in range(vertex_buffer_stride)), end=",\n")
|
|
print("}")
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
collada = parse.parse_collada_file(sys.argv[1])
|
|
|
|
mesh = collada.library_geometries[0].geometries[0].geometric_element
|
|
assert type(mesh) is types.Mesh
|
|
mesh_vertex_buffer(collada, mesh)
|