You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.5 KiB
Python

#!/usr/bin/env python3
import os
import sys
from pyffi.formats.nif import NifFormat
import json
def export(path):
data = NifFormat.Data()
with open(path, 'rb') as f:
data.inspect(f)
data.read(f)
objects = []
for root in data.roots:
name = root.name.decode('utf-8').lower()
# For this project, only hair and head matters
if 'hair' in name or 'head' in name:
sys.stderr.write("> " + name + "\n")
else:
sys.stderr.write(" " + name + "\n")
continue
if isinstance(root, NifFormat.NiNode):
objects.append(export_object(root))
# Some NiTriShape's are a root object
if isinstance(root, NifFormat.NiTriShape):
objects.append({'name': root.name.decode('utf-8'), 'shapes': [export_shape(root)]})
return objects
def export_object(root: NifFormat.NiNode):
obj = {'name': root.name.decode("utf-8"), 'shapes': []}
for shape in root.get_children():
if not isinstance(shape, NifFormat.NiTriShape):
continue
obj['shapes'].append(export_shape(shape))
return obj
def export_shape(shape: NifFormat.NiTriShape):
vertices = [(vertice.x, vertice.y, vertice.z) for vertice in list(shape.data.vertices)]
faces = shape.data.get_triangles()
uv_sets = [[[coord.u, coord.v] for coord in uv_set] for uv_set in shape.data.uv_sets]
normals = [(vertice.x, vertice.y, vertice.z) for vertice in list(shape.data.normals)]
texture = None
for property in shape.get_properties():
if isinstance(property, NifFormat.NiTexturingProperty):
texture = export_texture(property.base_texture)
return {
'name': shape.name.decode("utf-8"),
'vertices': vertices,
'faces': faces,
'uvSets': uv_sets,
'normals': normals,
'texture': texture,
'translation': (shape.translation.x, shape.translation.y, shape.translation.z),
'rotation': shape.rotation.as_list(),
}
def export_texture(texture):
wrap_s = texture.clamp_mode in [2, 3]
wrap_t = texture.clamp_mode in [1, 3]
source = texture.source
return {
'wrapS': wrap_s,
'wrapT': wrap_t,
'uvSet': texture.uv_set,
'file': source.file_name.decode("utf-8")
}
if __name__ == '__main__':
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <dir>")
exit(1)
objects = []
for item in os.scandir(sys.argv[1]):
if item.is_file():
objects.extend(export(item.path))
print(json.dumps(objects))