Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/formats/pmo.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ from [mhff](https://github.com/svanheulen/mhff) by Seth VanHeulen.
| 0x00 | `char[4]` | `pmo\0` |
| 0x04 | `char[4]` | Version, `1.0\0` or `102\0` |
| 0x08 | `u32` | Size: header, tables and geometry region. Bytes after it are the tail |
| 0x0C | `f32` | Clip distance; MHFU sets the largest scale component |
| 0x0C | `f32` | Cull-sphere radius before the entity's scale; MHFU sets the largest scale component, and 0 culls the model as a point |
| 0x10 | `f32[3]` | Scale (MHFU): multiplies the dequantised positions |
| 0x1C | `u16` | Mesh count |
| 0x1E | `u16` | Material count |
Expand Down
4 changes: 2 additions & 2 deletions packages/mhfu-port/src/mhfu_port/mesh.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2026 sp00ktober
"""The port's geometry: the donor's draw groups, and the MHFU PMO built from them once skinned."""
Expand Down Expand Up @@ -25,7 +25,6 @@
BLEND = 0
SHADOW = 0
COLOR = 0xFFFFFFFF
CLIP = 0.0
NO_NORMAL = (0.0, 0.0, 0.0)
"""Written for a donor vertex that carries no normal."""

Expand Down Expand Up @@ -162,7 +161,8 @@
groups = [group(s, scale, material_of[s.part.texture]) for s in skinned]
mesh = pmo.Mesh(groups, list(range(len(textures))), lighting=LIGHTING, blend=BLEND)
materials = [pmo.Material(color=COLOR, shadow=SHADOW, texture=t) for t in textures]
return pmo.Pmo([mesh], materials, scale, CLIP)
# the engine's cull sphere (Pmo.clip): 0 culls the model as a point near its feet
return pmo.Pmo([mesh], materials, scale, max(scale))


def group(skinned: Skinned, scale: Vec3, material: int = 0) -> pmo.Group:
Expand Down
4 changes: 2 additions & 2 deletions packages/mhfu-port/tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

PORTS = Path(__file__).parents[3] / "ports"
BUILT = {
"brute_tigrex": "a882bf01daf07df844a07da32fd6ff87ed10c9ecb1fec7e1eb207172e6ca5e29",
"zinogre": "3a0b11b7556678c66364d3357107a8ee130677d2c5fde9a43c7dfd5f82948f12",
"brute_tigrex": "1082b88cfaeee3086020a6b02ff59101dec4af8653ff44a4b56373a90ae87fae",
"zinogre": "830a4c15ed67a8760c0462fa8bcd5fc6548ca0b00b090089bb6d382c5e5e2256",
}
"""sha256 of each manifest's build: changes only with an intended change to the port."""
HEAD = '[port]\nname = "t"\nhost_species = 75\npac = "t.bin"\n[source]\nmodel = 5248\n'
Expand Down
6 changes: 3 additions & 3 deletions packages/mhfu-port/tests/test_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def test_build():
joint_of = {4: 1, 7: 2, 9: 3}
built = mesh.build(skin.source(parts, joint_of), SCALE)
back = fu.Pmo.from_bytes(built.to_bytes())
assert back == built and back.clip == mesh.CLIP and back.scale == SCALE
assert back == built and back.clip == max(SCALE) and back.scale == SCALE
assert [m.texture for m in back.materials] == [2, 6]
assert {(m.color, m.shadow) for m in back.materials} == {(mesh.COLOR, mesh.SHADOW)}
assert back.meshes[0].materials == [0, 1] and back.meshes[0].lighting == mesh.LIGHTING
Expand Down Expand Up @@ -163,8 +163,8 @@ def test_palette_limit():


DONORS = { # model, geometry: groups, vertices, triangles, sha256 of our PMO on an identity map
"brute": (5248, 5249, 88, 2862, 2973, "cb0d830eb6c61a09"),
"zinogre": (5339, 5340, 181, 4336, 4426, "98b3869f594ce302"),
"brute": (5248, 5249, 88, 2862, 2973, "ccc9f32546fdfcbb"),
"zinogre": (5339, 5340, 181, 4336, 4426, "09fd2847cff33e01"),
}


Expand Down
3 changes: 2 additions & 1 deletion packages/mhp-formats/src/mhp_formats/pmo.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ class Pmo:
scale: Vec3 = (1.0, 1.0, 1.0)
"""Multiplies the dequantised positions."""
clip: float = 0.0
"""Clipping distance; MHFU sets it to the largest scale component."""
"""Cull-sphere radius before the entity's scale, centred half a `scale.y` up; MHFU sets it to
the largest scale component, and 0 culls the model as a point."""
tail: bytes = b""
"""Bytes after the size the header declares (a standalone file pads to 0x800)."""

Expand Down
Loading