No project description provided
Project description
xc3_model_py
Python bindings to xc3_model for high level and efficient data access to model files for Xenoblade 1 DE, Xenoblade 2, and Xenoblade 3.
Introduction
Parsing and processing happens in optimized Rust code when calling xc3_model_py.load_map
or xc3_model_py.load_model
. All characters, models, and maps are converted to the same scene hierarchy representation. This avoids needing to add any special handling for maps vs characters. Pregenerated shader JSON databases are available from xc3_lib.
import xc3_model_py
# Get a list of model roots.
roots = xc3_model_py.load_map("xenoblade3_dump/map/ma59a.wismhd", database_path="xc3.json")
for root in roots:
for group in root.groups:
for models in group.models:
for material in models.materials:
print(material.name)
# The shader contains assignment information when specifying a JSON database.
if material.shader is not None:
# Find the image texture and channel used for the ambient occlusion output.
ao = material.shader.sampler_channel_index(2, 'z')
if ao is not None:
sampler_index, channel_index = ao
image_texture_index = material.textures[sampler_index].image_texture_index
image_texture = root.image_textures[image_texture_index]
print(image_texture.name, 'xyzw'[channel_index])
for model in models.models:
# prints (num_instances, 4, 4)
print(len(model.instances.shape))
# This returns only a single root.
root = xc3_model_py.load_model("xenoblade3_dump/chr/chr/01012013.wimdo", database_path="xc3.json")
for group in root.groups:
for models in group.models:
for model in models.models:
# prints (1, 4, 4)
print(len(model.instances.shape))
# Access vertex and index data for this model.
buffers = group.buffers[model.model_buffers_index]
for buffer in buffers.vertex_buffers:
for attribute in buffer.attributes:
print(attribute.attribute_type, attribute.data.shape)
Certain types like matrices and vertex atribute data are stored using numpy.ndarray
. This greatly reduces conversion overhead and allows for more optimized Python code. xc3_model_py requires the numpy package to be installed. Blender already provides the numpy package, enabling the use of functions like foreach_get
and foreach_set
for efficient property access.
# blender
blender_mesh.vertices.add(positions_array.shape[0])
blender_mesh.vertices.foreach_set('co', positions_array.reshape(-1))
Animations can be loaded from a file all at once. The track type is currently opaque, meaning that implementation details are not exposed. The values can be sampled at the desired frame using the appropriate methods.
import xc3_model_py
path = "xenoblade3_dump/chr/ch/ch01027000_event.mot"
animations = xc3_model_py.load_animations(path)
for animation in animations:
print(animation.name, animation.space_mode, animation.play_mode, animation.blend_mode)
print(f'frames: {animation.frame_count}, tracks: {len(animation.tracks)}')
track = animation.tracks[0]
# Each track references a bone in one of three ways.
bone_index = track.bone_index()
bone_hash = track.bone_hash()
bone_name = track.bone_name()
if bone_index is not None:
pass
elif bone_hash is not None:
# Use xc3_model_py.murmur3(bone_name) for hashing the skeleton bones.
pass
elif bone_name is not None:
pass
# Sample the transform for a given track at each frame.
# This essentially "bakes" the keyframes of the animation.
for frame in range(animation.frame_count:)
print(track.sample_scale(frame), track.sample_rotation(frame), track.sample_translation(frame))
print()
Documentation
See the pyi stub file for complete function and type information. This also enables autocomplete in supported editors like the Python extension for VSCode. The Python API attempts to match the Rust functions and types in xc3_model as closely as possible.
Installation
The compiled extension module can be imported just like any other Python file. On Windows, rename xc3_model_py.dll
to xc3_model_py.pyd
. If importing xc3_model_py
fails, make sure the import path is specified correctly and the current Python version matches the version used when building. For installing in the current Python environment, install maturin and use maturin develop --release
.
Building
Build the project with cargo build --release
. This will compile a native python module for the current Python interpreter. For use with Blender, make sure to build for the Python version used by Blender. The easiest way to do this is to use the Python interpreter bundled with Blender. See the PyO3 guide for details. Some example commands are listed below for different operating systems.
Blender 4.0 on Windows
set PYO3_PYTHON = "C:\Program Files\Blender Foundation\Blender 4.0\4.0\python\bin\python.exe"
cargo build --release
Blender 4.0 on MacOS
PYO3_PYTHON="/Applications/Blender.app/Contents/Resources/4.0/python/bin/python3.10" cargo build --release
Limitations
All data should be treated as immutable. Attempting to set fields will result in an error. Modifying list elements will appear to work, but changes will not be reflected when accessing the elements again. Types from xc3_model_py
also cannot be constructed in any way from Python. These limitations may be lifted in the future. Write support may be added in the future as xc3_lib and xc3_model develop.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Hashes for xc3_model_py-0.1.0-cp311-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0b5a82bb8504329a2c64f11c3746a22b72e52a80f7b35d7343a26f3b6f167e72 |
|
MD5 | a1a872b6b6d01482b1b2ebf107802857 |
|
BLAKE2b-256 | f9601b6df068702dc32c787e3ef12e5460517f83772b0e6679e20e987d111394 |
Hashes for xc3_model_py-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 449acdd72938630a44753d88fa3f7c61bf210a60642b505794f027d9ef8b395b |
|
MD5 | 38d23143b9aa74f0968b68c7bfe440b4 |
|
BLAKE2b-256 | 2597c9b3068557a37137223c0741d4aa13846db88cd84145cdf60c104c5328fa |
Hashes for xc3_model_py-0.1.0-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 87544503f012221ef614982ac781ea79537e749c4bf5af4b920d9a011a40c13e |
|
MD5 | 10d85b0d7892090547abe131589a57c7 |
|
BLAKE2b-256 | bd5d7209f731e46d3c99ba25178363b69916b41bb8967ca1456e75b36f3f1720 |
Hashes for xc3_model_py-0.1.0-cp310-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c40fbb100743a1616e800d399b38d4e7fbdacc63830e51df1b1c884f269c40ba |
|
MD5 | 4d0a0ae7579857aa01ea90e90f634284 |
|
BLAKE2b-256 | b388cf576fc186bac7ca324a3f483c0939651f05c66882126fb2af5e4b92ff9d |
Hashes for xc3_model_py-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2dc74ccbcb1a554a02baf8a4a404dcc4c4df921eee8c574861ff2bf7e0e8a816 |
|
MD5 | fd385f6609ab86048ff974ae3921f31f |
|
BLAKE2b-256 | b9e5de3004e27b37aa9a6b1cc4214896baf9a257a4f63a834b41060c58a6c1ec |
Hashes for xc3_model_py-0.1.0-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ebb5b23c5b65a63d438abb250ab850cb61bc7a98a1460881ab82badcf50e479b |
|
MD5 | 2a62031920144cb56c4dd4ef3039934a |
|
BLAKE2b-256 | 16f516b40c5dc4cb265d0c0e69fe6734c80208ef8679eebb00736dc81f87c8dd |
Hashes for xc3_model_py-0.1.0-cp39-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1112faa7c789eaf4e712bb0f613ff2c30c0e099829c595d3f9ee5e6495ed2c1c |
|
MD5 | 59bc1679938844b44676c0da11bcde26 |
|
BLAKE2b-256 | 8e7ae3ad6094e9e8ff5812bafd7b391496df0eea19ae10350904f24b68bd4bea |
Hashes for xc3_model_py-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 024c631b386aa459adc87ace96e93a543e17dc6e77f47b4850e7f79974b18be2 |
|
MD5 | de8cfeda1c0d4fa7cd4bb00a542588f0 |
|
BLAKE2b-256 | 7e1455314fb7247c1b624e225d1347c8882702e0ffc39f11890472ce68afc4cf |
Hashes for xc3_model_py-0.1.0-cp39-cp39-macosx_10_12_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d28bd912adfd2e984366602e58f2d83f0fe25c9ba407247c7a0b2807c9cef6f8 |
|
MD5 | c2d6c92b052dff1e8b0427522e4bb1a8 |
|
BLAKE2b-256 | fd246112c0f9e9816c2f55a3cfb2d128cfc0ea82dd231cec5304cf385e96352e |