EuropaTools/hexpat/mesh_researcher_pro_msh.py
2025-01-05 20:36:48 -05:00

96 lines
2.6 KiB
Python

#
# EuropaTools
#
# (C) 2021-2022 modeco80 <lily.modeco80@protonmail.ch>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This is a Model Researcher Pro script which can be used
# to automatically display .msh meshes inside of it.
#
# While I haven't written a native exporter yet, this should *not*
# be considered a replacement for that, especially given the issues:
# - python (its slow as balls)
# - Model Researcher is Windows-only
# - Generally this is just a quick hack and it shows in code quality.
import mrp
bf = mrp.get_bfile()
# read '\r\n' terminated string
# why the fuck did they do this
def Storage_ReadLine():
ret = ""
rntest = b""
while True:
a = bf.reads("1s")[0]
if a == b'\r' or a == b'\n':
rntest += a
if rntest == b'\r\n':
return ret
else:
ret += a.decode('ascii')
def ReadMeshBlock(readCallback):
count = bf.readShort()
data = None
if count != 0:
data = readCallback(count)
return (count, data)
def ReadVec3(count):
return bf.read(count * (3 * 4))
def ReadVertexColors(count):
return bf.read(count * 4)
def ReadFaces(count):
return bf.read(count * (3 * 2))
# main
# Make sure this is a MESH and it's a 2.0 version
# 1.2 version is actually text-format and I can't be bothered
# to support it.
if Storage_ReadLine() != 'MESH':
raise ValueError('not a Europa msh')
if Storage_ReadLine() != '2.0':
raise ValueError('not a Europa msh 2.0 (this parses only binary version 2.0)')
mesh_count = bf.readShort()
for i in range(0, mesh_count):
mtlFilename = Storage_ReadLine()
# read some pieces
verts = ReadMeshBlock(ReadVec3)
vertcolors = ReadMeshBlock(ReadVertexColors)
normals = ReadMeshBlock(ReadVec3)
# Need to manually ReadMeshBlock() here
# since we need vert count to read the UV block
uvCount = bf.readShort()
uv = None
if uvCount != 0:
print(f' {uvCount} uvs')
uv = []
for i in range(0, uvCount):
uv_bytes = bf.read(verts[0] * (2 * 4))
uv.append(uv_bytes)
faces = ReadMeshBlock(ReadFaces)
# Add it and set everything up, add verts, faces,
# and normals/UV if provided
mesh = mrp.create_mesh(mtlFilename)
mesh.set_vertices(verts[1], tp="Float")
mesh.set_faces(faces[1], tp="Short")
if normals[0] != 0:
mesh.set_normals(normals[1], tp="Float")
if uvCount != 0:
mesh.set_uvs(uv[0], tp="Float")
print(f'Read mesh {mtlFilename}')
mrp.render("All")