summaryrefslogtreecommitdiff
path: root/tools/converters/extract_model_data.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/converters/extract_model_data.py')
-rw-r--r--tools/converters/extract_model_data.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/tools/converters/extract_model_data.py b/tools/converters/extract_model_data.py
new file mode 100644
index 00000000..bd05e7a3
--- /dev/null
+++ b/tools/converters/extract_model_data.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+
+from argparse import ArgumentParser
+import struct
+import os
+from enum import Enum
+from binary_funcs import read_f32, read_u8
+
+def write_array_declaration(c_file, symbol_name: str, scope: str, type: str):
+ if scope == "local":
+ var_def_prefix = "static "
+ else:
+ var_def_prefix = ""
+
+ c_file.write(f"{var_def_prefix}{type} {symbol_name}[] = {{\n")
+
+def format_float_array(elements: list[tuple[float, ...]]) -> str:
+ if len(elements) == 0:
+ return ""
+
+ num_components: int = len(elements[0])
+
+ # Get the longest float for each component
+ longest_components: list[int] = [0] * num_components
+ for element in elements:
+ for i, component in enumerate(element):
+ length = len(f"{component:f}".rstrip('0'))
+ if f"{component:f}".rstrip('0').endswith('.'):
+ length += 1
+ longest_components[i] = max(length, longest_components[i])
+
+ result: str = ""
+ for element in elements:
+ # Open each array element
+ result += " {"
+ for i, component in enumerate(element):
+ # Remove all the trailing 0s (unless the value would end with the decimal point)
+ value = f'{component:f}'.rstrip('0')
+ if value.endswith('.'):
+ value += '0'
+
+ # Only add the comma + minimum 1 space if this isn't the last element
+ if i != len(element) - 1:
+ result += f"{f'{value}f, ':<{longest_components[i] + 3}}"
+ else:
+ result += f"{f'{value}f':<{longest_components[i] + 1}}"
+
+ result += "},\n"
+
+ return result
+
+def convert_binary_to_Vec_c_source(src_path: str, dest_path: str, symbol_name: str, scope: str):
+ # Load data
+ with open(src_path, "rb") as binary_file, open(dest_path, "w") as c_file:
+
+ write_array_declaration(c_file, symbol_name, scope, "Vec")
+
+ elements: list[tuple[float, ...]] = []
+ while True:
+ try:
+ x, y, z = read_f32(binary_file), read_f32(binary_file), read_f32(binary_file)
+ except EOFError:
+ break
+
+ elements.append((x, y, z))
+
+ lines = format_float_array(elements)
+ c_file.write(lines)
+
+ c_file.write("};\n")
+
+def convert_binary_to_cXy_c_source(src_path: str, dest_path: str, symbol_name: str, scope: str):
+ # Load data
+ with open(src_path, "rb") as binary_file, open(dest_path, "w") as c_file:
+
+ write_array_declaration(c_file, symbol_name, scope, "cXy")
+
+ elements: list[tuple[float, ...]] = []
+ while True:
+ try:
+ x, y = read_f32(binary_file), read_f32(binary_file)
+ except EOFError:
+ break
+
+ elements.append((x, y))
+
+ lines = format_float_array(elements)
+ c_file.write(lines)
+
+ c_file.write("};\n")
+
+def convert_binary_to_GXColor_c_source(src_path: str, dest_path: str, symbol_name: str, scope: str):
+ # Load data
+ with open(src_path, "rb") as binary_file, open(dest_path, "w") as c_file:
+
+ write_array_declaration(c_file, symbol_name, scope, "GXColor")
+
+ while True:
+ try:
+ r, g, b, a = read_u8(binary_file), read_u8(binary_file), read_u8(binary_file), read_u8(binary_file)
+ except EOFError:
+ break
+
+ c_file.write(" " + f"{{0x{r:02X}, 0x{g:02X}, 0x{b:02X}, 0x{a:02X}}}" + ",\n")
+
+ c_file.write("};\n")
+
+
+def main():
+ parser = ArgumentParser(
+ description="Converts a binary file containing vertex data to an array of the specified type"
+ )
+ parser.add_argument("src_path", type=str, help="Binary source file path")
+ parser.add_argument("dest_path", type=str, help="Destination C include file path")
+ parser.add_argument(
+ "--type",
+ type=str,
+ help="Data type",
+ )
+ parser.add_argument(
+ "--symbol",
+ type=str,
+ help="Symbol name",
+ )
+ parser.add_argument(
+ "--scope",
+ choices=["global", "local"],
+ default="local",
+ help="The scope of the symbol",
+ )
+
+ args = parser.parse_args()
+
+ if args.type == "Vec":
+ convert_binary_to_Vec_c_source(args.src_path, args.dest_path, args.symbol, args.scope)
+ elif args.type == "cXy":
+ convert_binary_to_cXy_c_source(args.src_path, args.dest_path, args.symbol, args.scope)
+ elif args.type == "GXColor":
+ convert_binary_to_GXColor_c_source(args.src_path, args.dest_path, args.symbol, args.scope)
+ else:
+ raise Exception(f"Unknown data type: {args.type}")
+
+
+if __name__ == "__main__":
+ main()