Browse Source

Initial commit and push

master
itdominator 5 months ago
parent
commit
f2efb7c42d
  1. 228
      src/blender_addon/io_mesh_msh2/__init__.py
  2. 13
      src/blender_addon/io_mesh_msh2/cli.py
  3. 74
      src/blender_addon/io_mesh_msh2/export_msh2.py
  4. 48
      src/blender_addon/io_mesh_msh2/import_msh2.py
  5. 59
      src/blender_addon/io_mesh_msh2/msh2/Logger.py
  6. 1
      src/blender_addon/io_mesh_msh2/msh2/__init__.py
  7. 0
      src/blender_addon/io_mesh_msh2/msh2/__main__.py
  8. 37
      src/blender_addon/io_mesh_msh2/msh2/msh2.py
  9. 154
      src/blender_addon/io_mesh_msh2/msh2/msh2_crc.py
  10. 2765
      src/blender_addon/io_mesh_msh2/msh2/msh2_data.py
  11. 593
      src/blender_addon/io_mesh_msh2/msh2/msh2_unpack.py
  12. 12
      src/clear_pycache_dirs.sh
  13. 4
      src_research_readme/Notes.txt
  14. 4005
      src_research_readme/mesh-info-pages/index.html
  15. 559
      src_research_readme/mesh-info-pages/msh Format_files/subpage-style.css
  16. 275
      src_research_readme/zero-edit-tool-python-base/Application/Core/zetcore.py
  17. 999
      src_research_readme/zero-edit-tool-python-base/Application/Core/zetexport.py
  18. 956
      src_research_readme/zero-edit-tool-python-base/Application/Core/zetimport.py
  19. 100
      src_research_readme/zero-edit-tool-python-base/Application/Logic/cloth.py
  20. 122
      src_research_readme/zero-edit-tool-python-base/Application/Logic/exporter.py
  21. 115
      src_research_readme/zero-edit-tool-python-base/Application/Logic/importer.py
  22. 256
      src_research_readme/zero-edit-tool-python-base/Application/Logic/material_manager.py
  23. 31
      src_research_readme/zero-edit-tool-python-base/Application/Logic/misc.py
  24. 46
      src_research_readme/zero-edit-tool-python-base/Application/Logic/mshjson.py
  25. 43
      src_research_readme/zero-edit-tool-python-base/Application/Logic/zetools.py
  26. 9
      src_research_readme/zero-edit-tool-python-base/Application/Modules/andecore.py
  27. 2767
      src_research_readme/zero-edit-tool-python-base/Application/Modules/msh2.py
  28. 149
      src_research_readme/zero-edit-tool-python-base/Application/Modules/msh2_crc.py
  29. 596
      src_research_readme/zero-edit-tool-python-base/Application/Modules/msh2_unpack.py
  30. 77
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/__init__.py
  31. 369
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/adapters.py
  32. 120
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/api.py
  33. 180
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/auth.py
  34. 3290
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/cacert.pem
  35. 24
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/certs.py
  36. 115
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/compat.py
  37. 406
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/cookies.py
  38. 59
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/exceptions.py
  39. 45
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/hooks.py
  40. 730
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/models.py
  41. 3
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/__init__.py
  42. 32
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/__init__.py
  43. 925
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/big5freq.py
  44. 42
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/big5prober.py
  45. 231
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/chardistribution.py
  46. 106
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/charsetgroupprober.py
  47. 62
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/charsetprober.py
  48. 61
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/codingstatemachine.py
  49. 34
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/compat.py
  50. 39
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/constants.py
  51. 44
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/cp949prober.py
  52. 86
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/escprober.py
  53. 242
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/escsm.py
  54. 90
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/eucjpprober.py
  55. 596
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/euckrfreq.py
  56. 42
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/euckrprober.py
  57. 428
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/euctwfreq.py
  58. 41
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/euctwprober.py
  59. 472
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/gb2312freq.py
  60. 41
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/gb2312prober.py
  61. 283
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/hebrewprober.py
  62. 569
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/jisfreq.py
  63. 219
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/jpcntx.py
  64. 229
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langbulgarianmodel.py
  65. 329
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langcyrillicmodel.py
  66. 225
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langgreekmodel.py
  67. 201
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langhebrewmodel.py
  68. 225
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langhungarianmodel.py
  69. 200
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/langthaimodel.py
  70. 139
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/latin1prober.py
  71. 86
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/mbcharsetprober.py
  72. 54
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/mbcsgroupprober.py
  73. 575
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/mbcssm.py
  74. 120
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/sbcharsetprober.py
  75. 69
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/sbcsgroupprober.py
  76. 91
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/sjisprober.py
  77. 172
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/universaldetector.py
  78. 76
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/charade/utf8prober.py
  79. 58
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/__init__.py
  80. 94
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/_collections.py
  81. 745
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/connectionpool.py
  82. 0
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/contrib/__init__.py
  83. 120
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/contrib/ntlmpool.py
  84. 344
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/contrib/pyopenssl.py
  85. 121
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/exceptions.py
  86. 177
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/fields.py
  87. 101
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/filepost.py
  88. 4
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/packages/__init__.py
  89. 260
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/packages/ordered_dict.py
  90. 385
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/packages/six.py
  91. 98
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py
  92. 259
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/poolmanager.py
  93. 142
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/request.py
  94. 301
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/response.py
  95. 626
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/packages/urllib3/util.py
  96. 527
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/sessions.py
  97. 88
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/status_codes.py
  98. 128
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/structures.py
  99. 571
      src_research_readme/zero-edit-tool-python-base/Application/Modules/requests/utils.py
  100. 308
      src_research_readme/zero-edit-tool-python-base/Application/Modules/softimage.py

228
src/blender_addon/io_mesh_msh2/__init__.py

@ -0,0 +1,228 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
from .msh2 import msh2
msh = msh2.MSH2(None)
bl_info = {
"name": "Zero Editor MSH2 format",
"author": "Maxim Stewart",
"version": (0, 0, 1),
"blender": (2, 74, 0),
"location": "File > Import-Export",
"description": "Import-Export Zero Editor MSH2 models, meshs, and textures",
"warning": "",
"wiki_url": "https://schlechtwetterfront.github.io/ze_filetypes/msh.html",
"category": "Import-Export"}
if "bpy" in locals():
import importlib
if "import_msh2" in locals():
importlib.reload(import_msh2)
if "export_msh2" in locals():
importlib.reload(export_msh2)
import bpy
from bpy.props import (
CollectionProperty,
BoolProperty,
FloatProperty,
StringProperty,
EnumProperty,
)
from bpy_extras.io_utils import (
ImportHelper,
ExportHelper,
orientation_helper_factory,
path_reference_mode,
axis_conversion,
)
from bpy.types import OperatorFileListElement
# NOTE: NEED to see what ZERO Engine uses as forward
IOOBJOrientationHelper = orientation_helper_factory("IOOBJOrientationHelper", axis_forward='-Z', axis_up='Y')
class ImportMSH2(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper):
"""Load a MSH2 File"""
bl_idname = "import_zero_editor_msh2.msh"
bl_label = "Zero Editor Import MSH2"
bl_options = {'REGISTER', 'UNDO'}
filename_ext = ".msh"
filter_glob = StringProperty(
default = "*.msh;*.tga",
options = {'HIDDEN'},
)
files = CollectionProperty(
name="File Path",
type=OperatorFileListElement,
)
directory = StringProperty(
subtype='DIR_PATH',
)
use_image_search = BoolProperty(
name="Image Search",
description="Search subdirs for any associated images "
"(Warning, may be slow)",
default=True,
)
def execute(self, context):
keywords = self.as_keywords(ignore=("axis_forward",
"axis_up",
"filter_glob",
"split_mode",
))
keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES')
if bpy.data.is_saved and context.user_preferences.filepaths.use_relative_paths:
import os
keywords["relpath"] = os.path.dirname(bpy.data.filepath)
data = {**keywords}
msh.import_file(data["filepath"])
return {'FINISHED'}
# def draw(self, context):
# layout = self.layout
#
# row = layout.row(align=True)
# row.prop(self, "use_smooth_groups")
# row.prop(self, "use_edges")
#
# box = layout.box()
# row = box.row()
# row.prop(self, "split_mode", expand=True)
#
# row = box.row()
# if self.split_mode == 'ON':
# row.label(text="Split by:")
# row.prop(self, "use_split_objects")
# row.prop(self, "use_split_groups")
# else:
# row.prop(self, "use_groups_as_vgroups")
#
# row = layout.split(percentage=0.67)
# row.prop(self, "global_clamp_size")
# layout.prop(self, "axis_forward")
# layout.prop(self, "axis_up")
#
# layout.prop(self, "use_image_search")
class ExportMSH2(bpy.types.Operator, ExportHelper, IOOBJOrientationHelper):
"""Save a MSH2 File"""
bl_idname = "export_zero_editor_msh2.msh"
bl_label = 'Zero Editor Export MSH2'
# # context group
filename_ext = ".msh"
filter_glob = StringProperty(
default = "*.msh;*.tga",
options = {'HIDDEN'},
)
use_selection = BoolProperty(
name = "Selection Only",
description = "Export selected objects only",
default = False,
)
use_animation = BoolProperty(
name="Animation",
description="Write out an OBJ for each frame",
default=False,
)
use_uvs = BoolProperty(
name="Include UVs",
description="Write out the active UV coordinates",
default=True,
)
use_materials = BoolProperty(
name="Write Materials",
description="Write out the MTL file",
default=True,
)
use_triangles = BoolProperty(
name="Triangulate Faces",
description="Convert all faces to triangles",
default=False,
)
def execute(self, context):
keywords = self.as_keywords(ignore=("axis_forward",
"axis_up",
"global_scale",
"check_existing",
"filter_glob",
))
data = {**keywords}
# msh.export_file()
# print("")
# print("")
# print(context)
# print("")
# print("")
msh.export_file(data["filepath"])
return {'FINISHED'}
classes = (
ImportMSH2,
ExportMSH2,
)
def menu_import(self, context):
self.layout.operator(ImportMSH2.bl_idname, text="Zero Editor MSH2 (.msh)")
def menu_export(self, context):
self.layout.operator(ExportMSH2.bl_idname, text="Zero Editor MSH2 (.msh)")
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.INFO_MT_file_import.append(menu_import)
bpy.types.INFO_MT_file_export.append(menu_export)
def unregister():
bpy.types.INFO_MT_file_import.remove(menu_import)
bpy.types.INFO_MT_file_export.remove(menu_export)
for cls in classes:
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()

13
src/blender_addon/io_mesh_msh2/cli.py

@ -0,0 +1,13 @@
# from msh2.MSH2 import MSH2
#
# msh2 = MSH2(None)
from msh2 import msh2
msh = msh2.MSH2(None)
msh.import_file("../../msh/all_weap_inf_lightsabre.msh")
# msh.export_file("all_weap_inf_lightsabre.msh")

74
src/blender_addon/io_mesh_msh2/export_msh2.py

@ -0,0 +1,74 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
This script exports a MSH2 file from Blender.
Usage:
Run this script from "File->Export" menu and then MSH2 file.
Note, This exports mesh objects and materials only, nurbs and curves are not supported.
https://schlechtwetterfront.github.io/ze_filetypes/msh.html
"""
# def save(context,
# filepath,
# *,
# use_triangles=False,
# use_edges=True,
# use_normals=False,
# use_smooth_groups=False,
# use_smooth_groups_bitflags=False,
# use_uvs=True,
# use_materials=True,
# use_mesh_modifiers=True,
# use_mesh_modifiers_render=False,
# use_blen_objects=True,
# group_by_object=False,
# group_by_material=False,
# keep_vertex_order=False,
# use_vertex_groups=False,
# use_nurbs=True,
# use_selection=True,
# use_animation=False,
# global_matrix=None,
# path_mode='AUTO'
# ):
#
# _write(context, filepath,
# EXPORT_TRI=use_triangles,
# EXPORT_EDGES=use_edges,
# EXPORT_SMOOTH_GROUPS=use_smooth_groups,
# EXPORT_SMOOTH_GROUPS_BITFLAGS=use_smooth_groups_bitflags,
# EXPORT_NORMALS=use_normals,
# EXPORT_UV=use_uvs,
# EXPORT_MTL=use_materials,
# EXPORT_APPLY_MODIFIERS=use_mesh_modifiers,
# EXPORT_APPLY_MODIFIERS_RENDER=use_mesh_modifiers_render,
# EXPORT_BLEN_OBS=use_blen_objects,
# EXPORT_GROUP_BY_OB=group_by_object,
# EXPORT_GROUP_BY_MAT=group_by_material,
# EXPORT_KEEP_VERT_ORDER=keep_vertex_order,
# EXPORT_POLYGROUPS=use_vertex_groups,
# EXPORT_CURVE_AS_NURBS=use_nurbs,
# EXPORT_SEL_ONLY=use_selection,
# EXPORT_ANIMATION=use_animation,
# EXPORT_GLOBAL_MATRIX=global_matrix,
# EXPORT_PATH_MODE=path_mode,
# )
#
# return {'FINISHED'}

48
src/blender_addon/io_mesh_msh2/import_msh2.py

@ -0,0 +1,48 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
This script imports a MSH2 files to Blender.
Usage:
Run this script from "File->Import" menu and then load the desired MSH2 file.
Note, This loads mesh objects and materials only, nurbs and curves are not supported.
https://schlechtwetterfront.github.io/ze_filetypes/msh.html
"""
# def load(context,
# filepath,
# *,
# global_clamp_size=0.0,
# use_smooth_groups=True,
# use_edges=True,
# use_split_objects=True,
# use_split_groups=True,
# use_image_search=True,
# use_groups_as_vgroups=False,
# use_cycles=True,
# relpath=None,
# global_matrix=None
# ):
# """
# Called by the user interface or another script.
# load_msh2(path) - should give acceptable results.
# This function passes the file and sends the data off
# to be split into objects and then converted into mesh objects
# """

59
src/blender_addon/io_mesh_msh2/msh2/Logger.py

@ -0,0 +1,59 @@
# Python imports
import os, logging
# Application imports
class Logger:
def __init__(self, name = "NO_LOGGER_NAME_PASSED_ON_INIT"):
self.logger = self.create_logger(name)
def get_logger(self):
return self.logger
def create_logger(self, loggerName, createFile = True):
"""
Create a new logging object and return it.
:note:
NOSET # Don't know the actual log level of this... (defaulting or literally none?)
Log Levels (From least to most)
Type Value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
:param loggerName: Sets the name of the logger object. (Used in log lines)
:param createFile: Whether we create a log file or just pump to terminal
:return: the logging object we created
"""
globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
chLogLevel = logging.CRITICAL # Prety musch the only one we change ever
fhLogLevel = logging.DEBUG
log = logging.getLogger(loggerName)
log.setLevel(globalLogLvl)
# Set our log output styles
fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S')
cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s')
ch = logging.StreamHandler()
ch.setLevel(level=chLogLevel)
ch.setFormatter(cFormatter)
log.addHandler(ch)
if createFile:
folder = "logs"
file = folder + "/flask-application.log"
if not os.path.exists(folder):
os.mkdir(folder)
fh = logging.FileHandler(file)
fh.setLevel(level=fhLogLevel)
fh.setFormatter(fFormatter)
log.addHandler(fh)
return log

1
src/blender_addon/io_mesh_msh2/msh2/__init__.py

@ -0,0 +1 @@
from . import *

0
src/blender_addon/io_mesh_msh2/msh2/__main__.py

37
src/blender_addon/io_mesh_msh2/msh2/msh2.py

@ -0,0 +1,37 @@
# Python imports
import faulthandler
import traceback
# Gtk imports
# Application imports
from . import msh2_unpack
class MSH2():
"""docstring for MSH2."""
def __init__(self, arg):
faulthandler.enable() # For better debug info
self.arg = arg
self.msh_config = {'do_logging': True, 'ignore_geo': False, 'triangulate': False}
self.msh = None
def import_file(self, file_name):
try:
self.msh = msh2_unpack.MSHUnpack(file_name, self.msh_config).unpack()
except Exception as e:
traceback.print_exc()
def export_file(self, file_name):
try:
self.msh.save(file_name)
except Exception as e:
traceback.print_exc()
def export_file_to_binary_json(self, file_name):
try:
self.msh.save_json(file_name)
except Exception as e:
traceback.print_exc()

154
src/blender_addon/io_mesh_msh2/msh2/msh2_crc.py

@ -0,0 +1,154 @@
'''
ZeroEngine .msh model format CRC algorithm.
Refer to
schlechtwetterfront.github.io/ze_filetypes/msh.html
for more information regarding the file format.
'''
# Python imports
from struct import pack
# Gtk imports
# Application imports
class CRCError(Exception):
def __init__(self, val):
self.val = val
def __str__(self):
return '{0}'.format(self.val)
# CRC lookup table.
TABLE_32 = (
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
)
# Used to calculate the lowercase CRC.
TOLOWER = (
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
)
def return_lowest_bits(n):
'''Simulate unsigned behavior.'''
return n & 0xFFFFFFFF
def crc(string):
'''Calculate the Zero CRC from string and return it as number.'''
crc_ = 0
crc_ = return_lowest_bits(~crc_)
if string:
for char in string:
ind = (crc_ >> 24)
ind = ind ^ TOLOWER[ord(char)]
crc_ = return_lowest_bits(crc_ << 8) ^ TABLE_32[ind]
return return_lowest_bits(~crc_)
def strcrc(string):
'''Calculate the Zero CRC and return it in a structure usable in .msh files.'''
return pack('<I', crc(string))
def compare_crc_adv(possible_strings, crc_):
for string in possible_strings:
if crc_ == strcrc(string):
return string

2765
src/blender_addon/io_mesh_msh2/msh2/msh2_data.py

File diff suppressed because it is too large

593
src/blender_addon/io_mesh_msh2/msh2/msh2_unpack.py

@ -0,0 +1,593 @@
'''
ZeroEngine .msh model format parser.
Refer to
schlechtwetterfront.github.io/ze_filetypes/msh.html
for more information regarding the file format.
'''
from . import msh2_data as msh2
from struct import unpack as unpack
import logging
from .Logger import Logger
logging = Logger("Msh").get_logger()
STR_CODEC = 'utf-8'
CHUNK_LIST = ['HEDR', 'SHVO', 'MSH2',
'SINF', 'FRAM', 'CAMR',
'MATL', 'DATA', 'MATD', 'ATRB', 'TX0D', 'TX1D', 'TX2D', 'TX3D',
'MODL', 'MTYP', 'MNDX', 'PRNT', 'FLGS', 'TRAN', 'ENVL', 'SWCI',
'GEOM', 'SEGM', 'SHDW', 'MATI', 'POSL', 'NRML', 'UV0L', 'UV1L',
'UV2L', 'CLRL', 'CLRB', 'WGHT', 'NDXL', 'NDXT', 'STRP',
'CLTH', 'CTEX', 'CPOS', 'CUV0', 'FIDX', 'FWGT', 'SPRS', 'CPRS',
'BPRS', 'COLL',
'SKL2', 'BLN2', 'ANM2', 'CYCL', 'KFR3',
'NAME', 'BBOX', 'CL1L']
class UnpackError(Exception):
def __init__(self, val):
self.val = val
def __str__(self):
return str(self.val)
class Unpacker(object):
def unpack_header(self, data):
return data[:4].decode(), unpack('<L', data[4:])[0]
def unpack_str(self, data):
pass
# def log(self, text):
# logging.debug(text)
# def dont_log(self, *text):
# pass
def long(self, data):
return unpack('<L', data)[0]
def short(self, data):
return unpack('<H', data)[0]
def float(self, data):
return unpack('<f', data)[0]
class BBoxUnpacker(Unpacker):
def __init__(self, data):
self.bbox = msh2.BBox()
self.data = data
def unpack(self):
self.bbox.rotation = unpack('<ffff', self.data[:16])
self.bbox.center = unpack('<fff', self.data[16:28])
self.bbox.extents = unpack('<fff', self.data[28:40])
self.bbox.radius = unpack('<f', self.data[40:])[0]
return self.bbox
class MSHUnpack(Unpacker):
def __init__(self, mshfile, config={'do_logging': False,
'ignore_geo': False,
'triangulate': False}):
self.mshfile = mshfile
self.msh = msh2.Msh()
self.msh.animation = msh2.Animation(self.msh, 'maybe_empty')
self.config = config
# if not config['do_logging']:
# self.log = self.dont_log
def unpack(self):
with open(self.mshfile, 'rb') as mf:
# HEDR
bin, self.size = self.unpack_header(mf.read(8))
# MSH2 or SHVO
bin, self.msh2size = self.unpack_header(mf.read(8))
if bin == 'SHVO':
logging.debug('Skipping SHVO chunk.')
# Read the 4 content bytes of SHVO.
mf.read(4)
# that's definitely MSH2
bin, self.msh2size = self.unpack_header(mf.read(8))
mdlcoll = msh2.ModelCollection(self.msh)
self.msh.models = mdlcoll
while True:
hdr, size = self.unpack_header(mf.read(8))
logging.debug('Header, Size: {0}, {1}'.format(hdr, size))
if hdr == 'SINF':
si = InfoUnpacker(self, size, mf)
self.msh.info = si.unpack()
elif hdr == 'MATL':
num_materials = unpack('<L', mf.read(4))[0]
matcoll = msh2.MaterialCollection(self.msh)
for n in range(num_materials):
mat, matsize = self.unpack_header(mf.read(8))
logging.debug('Material, Size: {0}, {1}'.format(mat, matsize))
mat = MaterialUnpacker(self, matsize, mf)
matcoll.add(mat.unpack())
matcoll.assign_indices()
self.msh.materials = matcoll
elif hdr == 'MODL':
mdl = ModelUnpacker(self, size, mf)
mdlcoll.add(mdl.unpack())
elif hdr == 'CAMR':
mf.read(size)
elif hdr == 'LGHT':
mf.read(size)
elif hdr == 'SKL2':
numbones = unpack('<L', mf.read(4))[0]
bonecoll = msh2.BoneCollection(self.msh.animation)
for n in range(numbones):
bone = msh2.Bone(bonecoll)
bone.CRC = mf.read(4)
bone.set_name_from_crc()
bone.bone_type = unpack('<L', mf.read(4))[0]
bone.constrain = unpack('<f', mf.read(4))[0]
bone.bone1len = unpack('<f', mf.read(4))[0]
bone.bone2len = unpack('<f', mf.read(4))[0]
bonecoll.add(bone)
self.msh.animation.bones = bonecoll
elif hdr == 'BLN2':
# Ignore BLN2 as this only has one attribute(blend_factor).
# It's not clear which type this is and it's not important.
mf.read(size)
elif hdr == 'ANM2':
# Continue as this is only a header.
continue
elif hdr == 'CYCL':
num_cycles = unpack('<L', mf.read(4))[0]
cycles = []
for n in range(num_cycles):
cycle = msh2.Cycle(self.msh.animation)
cycle.name = mf.read(64).strip(b'\x00')
cycle.fps = unpack('<f', mf.read(4))[0]
cycle.style = unpack('<L', mf.read(4))[0]
cycle.frames = unpack('<LL', mf.read(8))
cycles.append(cycle)
self.msh.animation.cycles = cycles
self.msh.animation.cycle = cycles[0]
elif hdr == 'KFR3':
numbones = unpack('<L', mf.read(4))[0]
for n in range(numbones):
# Ingore the crc, usually the same order as before.
mf.read(4)
bone = self.msh.animation.bones[n]
bone.keyframe_type = unpack('<L', mf.read(4))[0]
numtran, numrot = unpack('<LL', mf.read(8))
tran = []
translation_frame_indices = []
rot = []
rotation_frame_indices = []
for i in range(numtran):
# Ignore the frame index.
translation_frame_indices.append(unpack('<L', mf.read(4))[0])
# Add X, Y, Z position tuple.
tran.append(unpack('<fff', mf.read(12)))
for i in range(numrot):
# Again, ignore the frame index.
rotation_frame_indices.append(unpack('<L', mf.read(4))[0])
# X, Y, Z, W quaternion translation tuple.
rot.append(unpack('<ffff', mf.read(16)))
bone.pos_keyframes = tran
bone.pos_keyframe_indices = translation_frame_indices
bone.rot_keyframes = rot
bone.rot_keyframe_indices = rotation_frame_indices
elif hdr == 'CL1L':
break
else:
logging.debug('Unrecognized chunk {0} in MSHUnpack.'.format(hdr))
raise UnpackError('Unrecognized chunk {0} in MSHUnpack (can be a valid chunk but doesnt fit into this unpack level).'.format(hdr))
break
for model in self.msh.models:
model.set_deformers_from_indices()
return self.msh
class ModelUnpacker(Unpacker):
def __init__(self, up, size, fh):
self.size = size
self.fh = fh
self.mdl = msh2.Model(up.msh)
self.up = up
def unpack(self):
logging.debug('Unpacking Model at {0}.'.format(self.fh.tell() - 8))
while True:
hdr, size = self.unpack_header(self.fh.read(8))
logging.debug('Model: Header, Size: {0}, {1}'.format(hdr, size))
if hdr == 'MTYP':
self.mdl.model_type = msh2.MODEL_TYPES_INT[unpack('<L', self.fh.read(4))[0]]
# RepSharpshooters MshEx exports MTYP as MYTP. Should work since the format update.
elif hdr == 'MYTP':
logging.info('Found RepSharpshooter MshEx type .msh. Continuing the import.')
self.mdl.model_type = msh2.MODEL_TYPES_INT[unpack('<L', self.fh.read(4))[0]]
elif hdr == 'NAME':
self.mdl.name = self.fh.read(size).strip(b'\x00')
elif hdr == 'MNDX':
self.mdl.index = unpack('<L', self.fh.read(4))[0]
elif hdr == 'PRNT':
self.mdl.parent_name = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
elif hdr == 'FLGS':
self.mdl.vis = unpack('<L', self.fh.read(4))[0]
elif hdr == 'TRAN':
scl = unpack('<fff', self.fh.read(12))
rot = unpack('<ffff', self.fh.read(16))
tra = unpack('<fff', self.fh.read(12))
self.mdl.transform = msh2.Transform(tra, rot, scl)
elif hdr == 'GEOM':
if self.up.config['ignore_geo']:
self.fh.read(size)
continue
# If this is a bone(MTYP 3) then set model type to geobone as
# it has geometry, too.
if self.mdl.model_type == 'bone':
self.mdl.model_type = 'geobone'
# Ignore the bbox header and size indicator. We dont need it.
self.fh.read(8)
bb = BBoxUnpacker(self.fh.read(44))
self.mdl.bbox = bb.unpack()
self.mdl.segments = msh2.SegmentCollection(self.mdl)
while True:
soc, ssize = self.unpack_header(self.fh.read(8))
logging.debug('Model Segments: Header, Size: {0}, {1}'.format(soc, ssize))
if soc == 'SEGM':
segm = GeometryUnpacker(self, ssize, self.fh)
self.mdl.segments.add(segm.unpack())
elif soc == 'CLTH':
segm = ClothUnpacker(self, ssize, self.fh)
self.mdl.segments.add(segm.unpack())
elif soc == 'ENVL':
num = unpack('<L', self.fh.read(4))[0]
inds = []
for n in range(num):
inds.append(unpack('<L', self.fh.read(4))[0])
self.mdl.deformer_indices = inds
else:
logging.debug('Unrecognized chunk {0} in ModelUnpack(Geometry).'.format(soc))
self.fh.seek(self.fh.tell() - 8)
break
elif hdr == 'SWCI':
self.mdl.collprim = True
prim_data = unpack('<Lfff', self.fh.read(16))
self.mdl.primitive = (prim_data[0], prim_data[1],
prim_data[2], prim_data[3])
else:
logging.debug('Unrecognized chunk {0} in ModelUnpack.'.format(hdr))
# Return to the position before the header.
self.fh.seek(self.fh.tell() - 8)
break
return self.mdl
class ClothUnpacker(Unpacker):
def __init__(self, up, size, fh):
self.up = up
self.size = size
self.fh = fh
self.seg = msh2.ClothGeometry(up.mdl)
def unpack(self):
logging.debug('---- Unpacking Cloth ----')
fixed = []
while True:
hdr, size = self.unpack_header(self.fh.read(8))
logging.debug('Cloth: Header, Size: {0}, {1}'.format(hdr, size))
if hdr == 'CTEX':
self.seg.texture = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
elif hdr == 'CPOS':
vertcoll = msh2.ClothVertexCollection(self.seg)
num = unpack('<L', self.fh.read(4))[0]
for n in range(num):
pos = unpack('<fff', self.fh.read(12))
vert = msh2.ClothVertex(pos)
vertcoll.add(vert)
self.seg.vertices = vertcoll
elif hdr == 'CUV0':
num = unpack('<L', self.fh.read(4))[0]
for n in range(num):
self.seg.vertices[n].uv = unpack('<ff', self.fh.read(8))
elif hdr == 'FIDX':
num = unpack('<L', self.fh.read(4))[0]
for n in range(num):
index = unpack('<L', self.fh.read(4))[0]
fixed.append(index)
self.seg.vertices[index].is_fixed = True
elif hdr == 'FWGT':
self.fh.read(4) # Number of points.
weights = self.fh.read(size - 4).split(b'\x00')
logging.debug('Cloth Deformers: {0}'.format(weights))
logging.debug('Cloth Fixed Points: {0}'.format(len(fixed)))
weights.remove('')
if len(weights) > 0:
for index, vertindex in enumerate(fixed):
self.seg.vertices[vertindex].deformer = weights[index]
elif hdr == 'CMSH':
num = unpack('<L', self.fh.read(4))[0]
facecoll = msh2.FaceCollection(self.seg)
for n in range(num):
face = msh2.Face()
face.vertices = unpack('<LLL', self.fh.read(12))
facecoll.add(face)
self.seg.faces = facecoll
elif hdr == 'SPRS':
num_constraints = self.long(self.fh.read(4))
s_constraints = []
for n in range(num_constraints):
s_constraints.append(unpack('<HH', self.fh.read(4)))
self.seg.stretch_constraints = s_constraints
elif hdr == 'CPRS':
num_constraints = self.long(self.fh.read(4))
c_constraints = []
for n in range(num_constraints):
c_constraints.append(unpack('<HH', self.fh.read(4)))
self.seg.cross_constraints = c_constraints
elif hdr == 'BPRS':
num_constraints = self.long(self.fh.read(4))
b_constraints = []
for n in range(num_constraints):
b_constraints.append(unpack('<HH', self.fh.read(4)))
self.seg.bend_constraints = b_constraints
elif hdr == 'COLL':
num_colls = self.long(self.fh.read(4))
for n in range(num_colls):
collision = msh2.ClothCollision()
collision.cloth = self.seg
name = []
while 1:
char = self.fh.read(1)
if char == b'\x00':
break
name.append(char)
collision.name = ''.join(name)
parent = []
while 1:
char = self.fh.read(1)
if char == b'\x00':
break
parent.append(char)
collision.parent = ''.join(parent)
collision.primitive_type = unpack('<L', self.fh.read(4))[0]
collision.primitive_data = unpack('<fff', self.fh.read(12))
self.seg.collisions.append(collision)
# COLL chunk seems to be padded with \x00 at the end to get an even size indicator.
while True:
if self.fh.read(1) == b'\x00':
continue
else:
self.fh.seek(self.fh.tell() - 1)
break
else:
logging.debug('Unrecognized chunk {0} in ClothUnpack.'.format(hdr))
# Return to the position before the header.
self.fh.seek(self.fh.tell() - 8)
break
return self.seg
class GeometryUnpacker(Unpacker):
def __init__(self, up, size, fh):
self.up = up
self.size = size
self.fh = fh
# Either SegmentGeometry or ShadowGeometry.
# Usually it's SegmentGeometry so we'll set it as default.
# Cloth doesn't have the SEGM chunk we read before we got here.
self.seg = msh2.SegmentGeometry(up.mdl)
def unpack(self):
# Now we have to check which type of segment it is.
# Most common will be static meshes, then maybe shadows, then enveloped.
# Enveloped and static meshes share most of the chunks, however,
# shadows meshes only have one chunk.
logging.debug('---- Unpacking Geometry ----')
self.up.up.last_chunk = None
while True:
# The SEGM header is already gone so read the next one.
hdr, size = self.unpack_header(self.fh.read(8))
logging.debug('Geo: Header, Size: {0}, {1}'.format(hdr, size))
if hdr == 'SHDW':
self.up.up.last_chunk = 'SHDW'
self.seg = msh2.ShadowGeometry(self.up.mdl)
# self.seg.data = self.fh.read(size)
num_pos = self.long(self.fh.read(4))
positions = []
for n in range(num_pos):
positions.append((self.float(self.fh.read(4)), self.float(self.fh.read(4)), self.float(self.fh.read(4))))
num_edges = self.long(self.fh.read(4))
edges = []
for n in range(num_edges):
edge = self.short(self.fh.read(2)), self.short(self.fh.read(2)), self.short(self.fh.read(2)), self.short(self.fh.read(2))
edges.append(edge)
self.seg.positions = positions
self.seg.edges = edges
elif hdr == 'MATI':
self.up.up.last_chunk = 'MATI'
# 1st up: ModelUnpacker, 2nd up: MSHUnpack
self.seg.material = self.up.up.msh.get_mat_by_index(unpack('<L', self.fh.read(4))[0])
self.seg.mat_name = self.seg.material.name
elif hdr == 'POSL':
self.up.up.last_chunk = 'POSL'
num_positions = unpack('<L', self.fh.read(4))[0]
vertcoll = msh2.VertexCollection(self.seg)
for n in range(num_positions):
pos = self.fh.read(12)
pos = unpack('<fff', pos)
vert = msh2.Vertex(pos)
vertcoll.add(vert)
self.seg.vertices = vertcoll
elif hdr == 'NRML':
self.up.up.last_chunk = 'NRML'
num_normals = unpack('<L', self.fh.read(4))[0]
for n in range(num_normals):
self.seg.vertices[n].normal = unpack('<fff', self.fh.read(12))
elif hdr == 'UV0L':
self.up.up.last_chunk = 'UV0L'
num_uvs = unpack('<L', self.fh.read(4))[0]
for n in range(num_uvs):
self.seg.vertices[n].uv = unpack('<ff', self.fh.read(8))
self.seg.vertices.uved = True
elif hdr in ('UV1L', 'UV2L', 'UV3L'):
# Never seen UV2L + but just to be sure.
self.fh.read(size)
elif hdr == 'CLRL':
self.up.up.last_chunk = 'CLRL'
num_colors = unpack('<L', self.fh.read(4))[0]
for n in range(num_colors):
bgra_color = unpack('<BBBB', self.fh.read(4))
self.seg.vertices[n].color = msh2.Color((bgra_color[2], bgra_color[1], bgra_color[0], bgra_color[3]))
self.seg.vertices.colored = True
elif hdr == 'CLRB':
self.up.up.last_chunk = 'CLRB'
bgra_color = unpack('<BBBB', self.fh.read(4))
color = (bgra_color[2], bgra_color[1], bgra_color[0], bgra_color[3])
for vert in self.seg.vertices:
vert.color = msh2.Color(color)
self.seg.vertices.colored = True
elif hdr == 'WGHT':
last_chunk = 'WGHT'
num = unpack('<L', self.fh.read(4))[0]
for n in range(num):
indices = []
vals = []
for i in range(4):
indices.append(unpack('<L', self.fh.read(4))[0])
vals.append(unpack('<f', self.fh.read(4))[0])
self.seg.vertices[n].deformer_indices = indices
self.seg.vertices[n].weights = vals
self.seg.vertices.weighted = True
elif hdr == 'STRP':
last_chunk = 'STRP'
num = unpack('<L', self.fh.read(4))[0]
facecoll = msh2.FaceCollection(self.seg)
num_begins = 0
for n in range(num):
val = unpack('<H', self.fh.read(2))[0]
if (val - 0x8000) > -1:
if num_begins == 0:
num_begins += 1
face = msh2.Face()
facecoll.add(face)
elif num_begins == 1:
num_begins += 1
if face.sides > 2:
face = msh2.Face()
facecoll.add(face)
num_begins = 0
elif num_begins == 2:
num_begins = 1
face = msh2.Face()
facecoll.add(face)
face.add(val - 0x8000)
else:
face.add(val)
facecoll.de_ngonize(self.up.up.config['triangulate'])
self.seg.faces = facecoll
elif hdr == 'NDXL':
last_chunk = 'NDXL'
self.fh.read(size)
elif hdr == 'NDXT':
last_chunk = 'NDXT'
# If the faces are already set (for example from the STRP chunk)
# then ignore this as it's usually deprecated.
if self.seg.faces:
continue
num_triangles = unpack('<L', self.fh.read(4))[0]
logging.debug('Sizes: %d == %d', num_triangles * 6 + 4, size)
faces = msh2.FaceCollection(self.seg)
for n in range(num_triangles):
face = msh2.Face(list(unpack('<HHH', self.fh.read(2 * 3))))
faces.add(face)
self.seg.faces = faces
# Skip any bytes left (which seems to happen in some .msh files),
used_bytes = len(faces) * 6 + 4
if used_bytes < size:
self.fh.read(size - used_bytes)
else:
if hdr not in CHUNK_LIST:
if last_chunk == 'STRP':
logging.debug('Fixing STRP chunk import.')
self.fh.seek(self.fh.tell() - 8)
self.fh.read(2)
continue
logging.debug('Unrecognized chunk {0} in GeometryUnpack.'.format(hdr))
# Return to the position before the header.
self.fh.seek(self.fh.tell() - 8)
break
return self.seg
class MaterialUnpacker(Unpacker):
def __init__(self, up, size, fh):
self.size = size
self.fh = fh
self.mat = msh2.Material(up.msh)
def unpack(self):
logging.debug('---- Unpacking Material ----')
# NAME chunk.
bin, size = self.unpack_header(self.fh.read(8))
self.mat.name = self.fh.read(size).strip(b'\x00')
# DATA chunk.
bin, size = self.unpack_header(self.fh.read(8))
logging.debug('header, size: {0}, {1}'.format(bin, size))
self.mat.diff_color = msh2.Color(unpack('<ffff', self.fh.read(16)))
self.mat.spec_color = msh2.Color(unpack('<ffff', self.fh.read(16)))
self.mat.ambt_color = msh2.Color(unpack('<ffff', self.fh.read(16)))
self.mat.gloss = unpack('<f', self.fh.read(4))[0]
# ATRB chunk.
bin, size = self.unpack_header(self.fh.read(8))
logging.debug('header, size: {0}, {1}'.format(bin, size))
self.mat.flags = self.mat.flags_from_int(unpack('<B', self.fh.read(1))[0])
self.mat.render_type, self.mat.data0, self.mat.data1 = unpack('<BBB', self.fh.read(3))
# Textures.
for n in range(4):
hdr, size = self.unpack_header(self.fh.read(8))
logging.debug('TX header, size: {0}, {1}'.format(hdr, size))
if hdr[:2] == 'TX':
if hdr[2] == '0':
self.mat.tex0 = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
elif hdr[2] == '1':
self.mat.tex1 = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
elif hdr[2] == '2':
self.mat.tex2 = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
elif hdr[2] == '3':
self.mat.tex3 = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
else:
logging.debug('Unrecognized chunk {0} in MaterialUnpacker.'.format(hdr))
self.fh.seek(self.fh.tell() - 8)
break
return self.mat
class InfoUnpacker(Unpacker):
def __init__(self, up, size, fh):
self.size = size
self.fh = fh
self.info = msh2.SceneInfo(up.msh)
def unpack(self):
logging.debug('---- Unpacking Scene Info ----')
# Name chunk.
bin, size = self.unpack_header(self.fh.read(8))
self.info.name = self.fh.read(size).decode().encode(STR_CODEC).strip(b'\x00')
# FRAM chunk.
bin, size = self.unpack_header(self.fh.read(8))
self.info.frame_range = unpack('<LL', self.fh.read(8))
self.info.fps = unpack('<f', self.fh.read(4))[0]
# BBOX chunk.
self.fh.read(8) # Just read those, size is always the same.
bb = BBoxUnpacker(self.fh.read(44))
self.info.bbox = bb.unpack()
return self.info

12
src/clear_pycache_dirs.sh

@ -0,0 +1,12 @@
#!/bin/bash
# set -o xtrace ## To debug scripts
# set -o errexit ## To exit on error
# set -o errunset ## To exit if a variable is referenced but not set
function main() {
find . -name "__pycache__" -exec rm -rf $1 {} \;
find . -name "*.pyc" -exec rm -rf $1 {} \;
}
main

4
src_research_readme/Notes.txt

@ -0,0 +1,4 @@
https://git.rwth-aachen.de/carstenf/OpenGL/blob/master/QtMeshViewer/Source/SettingsManager.cpp
https://schlechtwetterfront.github.io/ze_filetypes/msh.html

4005
src_research_readme/mesh-info-pages/index.html

File diff suppressed because it is too large

559
src_research_readme/mesh-info-pages/msh Format_files/subpage-style.css

@ -0,0 +1,559 @@
h1, h2, h3, h4, h5, h6,
.heading-1, .heading-2, .heading-3, .heading-4, .heading-5, .heading-6 {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
color: #222;
margin-top: 0;
font-weight: 400;
text-rendering: optimizeLegibility;
line-height: 1; }
h1, .heading-1 {
font-size: 3.333rem;
margin-bottom: 1.333rem;
padding-bottom: .666rem; }
h2, .heading-2 {
font-size: 2.899rem;
margin-bottom: 1rem;
padding-bottom: .666rem; }
h3, .heading-3 {
font-size: 2.133rem;
margin-bottom: .666rem;
padding-bottom: .4rem; }
h4, .heading-4 {
font-size: 1.666rem;
margin-bottom: .666rem;
padding-bottom: .333rem; }
h5, .heading-5 {
font-size: 1.133rem;
margin-bottom: 0.333rem;
padding-bottom: .333rem; }
h6, .heading-6 {
font-size: .799rem;
margin-bottom: 0.333rem;
padding-bottom: .333rem; }
h2, h3, h4, h5, h6 {
border-bottom: 1px solid rgba(0, 0, 0, 0.15); }
h2 {
margin-bottom: 1rem;
padding-bottom: .616161rem; }
p {
text-align: justify;
margin-bottom: 1rem;
margin-top: 0; }
small {
font-size: 65%; }
h1, h2, h3, h4, h5, h6, p {
hyphens: auto; }
.anchor {
font-size: 50%;
padding-right: .3em;
padding-left: .3em;
display: none; }
h1:hover .anchor, h2:hover .anchor, h3:hover .anchor, h4:hover .anchor, h5:hover .anchor, h6:hover .anchor {
display: inline; }
ul, ol {
margin: 0 0 1rem; }
ul li, ol li {
text-align: justify; }
ul li p, ol li p {
margin-bottom: 0; }
ul {
padding-left: 1.6rem; }
dl {
margin: 0; }
dl dt {
font-weight: bold; }
dl dd {
margin-left: 1.6rem; }
ol {
counter-reset: item;
padding: 0; }
ol > li {
counter-increment: item;
list-style-type: none;
text-indent: -1.6rem;
padding-left: 1.6rem; }
ol > li:before {
content: counter(item) ".";
display: inline-block;
text-align: right;
width: 1.3rem;
padding-right: .3rem;
font-weight: bold; }
ol > li.fancy-block:before {
background: black;
color: white; }
ul.collapsed {
list-style: none;
padding: 0; }
ul.collapsed li {
display: inline-block; }
ul.blocks, ol.blocks {
list-style: none;
padding: 0; }
pre, code {
font-family: Monaco, Consolas, monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
tab-size: 4; }
pre,
:not(pre) > code {
background: rgba(0, 0, 0, 0.066); }
pre {
border-radius: .199em;
margin: .5em 0;
padding: 1em; }
:not(pre) > code {
padding: .15em .2em .05em;
border-radius: .333em; }
h1 > code, h2 > code, h3 > code, h4 > code, h5 > code, h6 > code {
background: none; }
table {
width: 100%;
margin-bottom: 1rem;
border-collapse: collapse; }
table thead {
border-bottom: 2px solid rgba(0, 0, 0, 0.15); }
table thead .title {
text-transform: uppercase; }
table tbody tr:nth-child(odd) {
background: rgba(0, 0, 0, 0.033); }
table td, table th {
padding: .1rem .666rem;
text-align: left;
vertical-align: top; }
table td p, table th p {
margin: 0; }
.tags {
display: flex;
justify-content: space-between;
flex-direction: row-reverse;
flex-wrap: wrap; }
.tags .tag {
padding: .33em .66em;
background: rgba(0, 0, 0, 0.1);
border-radius: .3333em