Non-import changes removed
This commit is contained in:
parent
152b22feb9
commit
1cc6a8d08d
|
@ -1,57 +0,0 @@
|
||||||
""" Gathers the Blender objects from the current scene and returns them as a list of
|
|
||||||
Model objects. """
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
import math
|
|
||||||
from enum import Enum
|
|
||||||
from typing import List, Set, Dict, Tuple
|
|
||||||
from itertools import zip_longest
|
|
||||||
from .msh_model import *
|
|
||||||
from .msh_model_utilities import *
|
|
||||||
from .msh_utilities import *
|
|
||||||
from .msh_model_gather import *
|
|
||||||
|
|
||||||
|
|
||||||
def gather_animdata(armature: bpy.types.Armature) -> List[Animation]:
|
|
||||||
|
|
||||||
anim_data = Animation();
|
|
||||||
|
|
||||||
action = armature.animation_data.action
|
|
||||||
|
|
||||||
framerange = action.frame_range
|
|
||||||
increment = (framerange.y - framerange.x) / 20.0
|
|
||||||
offset = framerange.x;
|
|
||||||
|
|
||||||
anim_data.bone_transforms[armature.parent.name] = []
|
|
||||||
for bone in armature.data.bones:
|
|
||||||
anim_data.bone_transforms[bone.name] = []
|
|
||||||
|
|
||||||
for frame in range(21):
|
|
||||||
frame_time = offset + frame * increment
|
|
||||||
bpy.context.scene.frame_set(frame_time)
|
|
||||||
|
|
||||||
anim_data.bone_transforms[armature.parent.name].append(ModelTransform()) #for testing
|
|
||||||
|
|
||||||
for bone in armature.pose.bones:
|
|
||||||
xform = ModelTransform()
|
|
||||||
|
|
||||||
|
|
||||||
vt = convert_vector_space(bone.location);
|
|
||||||
|
|
||||||
xform.translation = Vector((vt.x * -1.0, vt.y, vt.z))
|
|
||||||
xform.rotation = convert_rotation_space(bone.rotation_quaternion)
|
|
||||||
|
|
||||||
'''
|
|
||||||
xform.translation = bone.location
|
|
||||||
xform.rotation = bone.rotation_quaternion
|
|
||||||
|
|
||||||
anim_data.bone_transforms[bone.name].append(xform)
|
|
||||||
'''
|
|
||||||
|
|
||||||
return [anim_data]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
saved to a .msh file. """
|
saved to a .msh file. """
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List, Dict, Tuple
|
from typing import List
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from mathutils import Vector, Quaternion
|
from mathutils import Vector, Quaternion
|
||||||
|
|
||||||
|
@ -37,8 +37,7 @@ class GeometrySegment:
|
||||||
normals: List[Vector] = field(default_factory=list)
|
normals: List[Vector] = field(default_factory=list)
|
||||||
colors: List[List[float]] = None
|
colors: List[List[float]] = None
|
||||||
texcoords: List[Vector] = field(default_factory=list)
|
texcoords: List[Vector] = field(default_factory=list)
|
||||||
|
# TODO: Skin support.
|
||||||
weights: List[Tuple[int, float]] = None
|
|
||||||
|
|
||||||
polygons: List[List[int]] = field(default_factory=list)
|
polygons: List[List[int]] = field(default_factory=list)
|
||||||
triangles: List[List[int]] = field(default_factory=list)
|
triangles: List[List[int]] = field(default_factory=list)
|
||||||
|
@ -66,13 +65,3 @@ class Model:
|
||||||
|
|
||||||
geometry: List[GeometrySegment] = None
|
geometry: List[GeometrySegment] = None
|
||||||
collisionprimitive: CollisionPrimitive = None
|
collisionprimitive: CollisionPrimitive = None
|
||||||
|
|
||||||
vgroups_to_modelnames_map : Dict[int, str] = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Animation:
|
|
||||||
""" Class representing 'CYCL' + 'KFR3' sections in a .msh file """
|
|
||||||
|
|
||||||
name: str = "open"
|
|
||||||
bone_transforms: Dict[str, List[ModelTransform]] = field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, Set, Dict, Tuple, Set
|
from typing import List, Set, Dict, Tuple
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
from .msh_model import *
|
from .msh_model import *
|
||||||
from .msh_model_utilities import *
|
from .msh_model_utilities import *
|
||||||
from .msh_utilities import *
|
from .msh_utilities import *
|
||||||
|
|
||||||
SKIPPED_OBJECT_TYPES = {"LATTICE", "CAMERA", "LIGHT", "SPEAKER", "LIGHT_PROBE", "ARMATURE"}
|
SKIPPED_OBJECT_TYPES = {"LATTICE", "CAMERA", "LIGHT", "SPEAKER", "LIGHT_PROBE"}
|
||||||
MESH_OBJECT_TYPES = {"MESH", "CURVE", "SURFACE", "META", "FONT", "GPENCIL"}
|
MESH_OBJECT_TYPES = {"MESH", "CURVE", "SURFACE", "META", "FONT", "GPENCIL"}
|
||||||
MAX_MSH_VERTEX_COUNT = 32767
|
MAX_MSH_VERTEX_COUNT = 32767
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ def gather_models(apply_modifiers: bool, export_target: str) -> List[Model]:
|
||||||
parents = create_parents_set()
|
parents = create_parents_set()
|
||||||
|
|
||||||
models_list: List[Model] = []
|
models_list: List[Model] = []
|
||||||
skeleton: bpy.types.Armature = None
|
|
||||||
|
|
||||||
for uneval_obj in select_objects(export_target):
|
for uneval_obj in select_objects(export_target):
|
||||||
if uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents:
|
if uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents:
|
||||||
|
@ -45,24 +44,11 @@ def gather_models(apply_modifiers: bool, export_target: str) -> List[Model]:
|
||||||
model.transform.translation = convert_vector_space(local_translation)
|
model.transform.translation = convert_vector_space(local_translation)
|
||||||
|
|
||||||
if obj.parent is not None:
|
if obj.parent is not None:
|
||||||
if obj.parent.type == "ARMATURE":
|
model.parent = obj.parent.name
|
||||||
skeleton = obj.parent
|
|
||||||
|
|
||||||
parent_bone_name = obj.parent_bone
|
|
||||||
if parent_bone_name == "":
|
|
||||||
model.parent = obj.parent.parent
|
|
||||||
else:
|
|
||||||
model.parent = parent_bone_name
|
|
||||||
|
|
||||||
if model.model_type == ModelType.SKIN:
|
|
||||||
model.vgroups_to_modelnames_map = {}
|
|
||||||
for i, vgroup in enumerate(obj.vertex_groups):
|
|
||||||
vgroups_to_modelnames_map[i] = vgroup.name
|
|
||||||
|
|
||||||
|
|
||||||
if obj.type in MESH_OBJECT_TYPES:
|
if obj.type in MESH_OBJECT_TYPES:
|
||||||
mesh = obj.to_mesh()
|
mesh = obj.to_mesh()
|
||||||
model.geometry = create_mesh_geometry(mesh, model.model_type == ModelType.SKIN)
|
model.geometry = create_mesh_geometry(mesh)
|
||||||
obj.to_mesh_clear()
|
obj.to_mesh_clear()
|
||||||
|
|
||||||
_, _, world_scale = obj.matrix_world.decompose()
|
_, _, world_scale = obj.matrix_world.decompose()
|
||||||
|
@ -80,30 +66,6 @@ def gather_models(apply_modifiers: bool, export_target: str) -> List[Model]:
|
||||||
|
|
||||||
models_list.append(model)
|
models_list.append(model)
|
||||||
|
|
||||||
|
|
||||||
for bone in skeleton.data.bones:
|
|
||||||
|
|
||||||
model = Model()
|
|
||||||
model.name = bone.name
|
|
||||||
model.model_type = ModelType.NULL
|
|
||||||
model.hidden = False
|
|
||||||
|
|
||||||
local_translation, local_rotation, _ = bone.matrix_local.decompose()
|
|
||||||
model.transform.rotation = convert_rotation_space(local_rotation)
|
|
||||||
model.transform.translation = convert_vector_space(local_translation)
|
|
||||||
|
|
||||||
parent_name = bone.parent
|
|
||||||
if parent_name is not None:
|
|
||||||
model.parent = parent_name
|
|
||||||
else:
|
|
||||||
if skeleton.parent is not None:
|
|
||||||
model.parent = skeleton.parent.name
|
|
||||||
else:
|
|
||||||
model.parent = None
|
|
||||||
|
|
||||||
models_list.append(model)
|
|
||||||
|
|
||||||
|
|
||||||
return models_list
|
return models_list
|
||||||
|
|
||||||
def create_parents_set() -> Set[str]:
|
def create_parents_set() -> Set[str]:
|
||||||
|
@ -118,7 +80,7 @@ def create_parents_set() -> Set[str]:
|
||||||
|
|
||||||
return parents
|
return parents
|
||||||
|
|
||||||
def create_mesh_geometry(mesh: bpy.types.Mesh, is_skinned : bool) -> List[GeometrySegment]:
|
def create_mesh_geometry(mesh: bpy.types.Mesh) -> List[GeometrySegment]:
|
||||||
""" Creates a list of GeometrySegment objects from a Blender mesh.
|
""" Creates a list of GeometrySegment objects from a Blender mesh.
|
||||||
Does NOT create triangle strips in the GeometrySegment however. """
|
Does NOT create triangle strips in the GeometrySegment however. """
|
||||||
|
|
||||||
|
@ -192,16 +154,6 @@ def create_mesh_geometry(mesh: bpy.types.Mesh, is_skinned : bool) -> List[Geomet
|
||||||
segment.positions.append(convert_vector_space(mesh.vertices[vertex_index].co))
|
segment.positions.append(convert_vector_space(mesh.vertices[vertex_index].co))
|
||||||
segment.normals.append(convert_vector_space(vertex_normal))
|
segment.normals.append(convert_vector_space(vertex_normal))
|
||||||
|
|
||||||
if is_skinned:
|
|
||||||
for i,grp_el in mesh.vertices[vertex_index].groups:
|
|
||||||
segment.weights.append(tuple(grp_el.group, grp_el.weight))
|
|
||||||
print("Adding weight to group {grp_el.group} of value {grp_el.weight}")
|
|
||||||
if i > 3: #will have to look into aramture/skin settings for limiting envolopes to 4 weights...
|
|
||||||
break
|
|
||||||
while i < 3:
|
|
||||||
segment.weights.append(tuple(0,0.0))
|
|
||||||
i+=1
|
|
||||||
|
|
||||||
if mesh.uv_layers.active is None:
|
if mesh.uv_layers.active is None:
|
||||||
segment.texcoords.append(Vector((0.0, 0.0)))
|
segment.texcoords.append(Vector((0.0, 0.0)))
|
||||||
else:
|
else:
|
||||||
|
@ -212,7 +164,6 @@ def create_mesh_geometry(mesh: bpy.types.Mesh, is_skinned : bool) -> List[Geomet
|
||||||
|
|
||||||
return new_index
|
return new_index
|
||||||
|
|
||||||
|
|
||||||
for tri in mesh.loop_triangles:
|
for tri in mesh.loop_triangles:
|
||||||
polygons[tri.material_index].add(tri.polygon_index)
|
polygons[tri.material_index].add(tri.polygon_index)
|
||||||
segments[tri.material_index].triangles.append([
|
segments[tri.material_index].triangles.append([
|
||||||
|
@ -230,8 +181,7 @@ def create_mesh_geometry(mesh: bpy.types.Mesh, is_skinned : bool) -> List[Geomet
|
||||||
|
|
||||||
def get_model_type(obj: bpy.types.Object) -> ModelType:
|
def get_model_type(obj: bpy.types.Object) -> ModelType:
|
||||||
""" Get the ModelType for a Blender object. """
|
""" Get the ModelType for a Blender object. """
|
||||||
if obj.parent_type == "ARMATURE":
|
# TODO: Skinning support, etc
|
||||||
return ModelType.SKIN
|
|
||||||
|
|
||||||
if obj.type in MESH_OBJECT_TYPES:
|
if obj.type in MESH_OBJECT_TYPES:
|
||||||
return ModelType.STATIC
|
return ModelType.STATIC
|
||||||
|
|
|
@ -6,7 +6,7 @@ from typing import List, Dict
|
||||||
from copy import copy
|
from copy import copy
|
||||||
import bpy
|
import bpy
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from .msh_model import Model, Animation
|
from .msh_model import Model
|
||||||
from .msh_model_gather import gather_models
|
from .msh_model_gather import gather_models
|
||||||
from .msh_model_utilities import sort_by_parent, has_multiple_root_models, reparent_model_roots, get_model_world_matrix
|
from .msh_model_utilities import sort_by_parent, has_multiple_root_models, reparent_model_roots, get_model_world_matrix
|
||||||
from .msh_model_triangle_strips import create_models_triangle_strips
|
from .msh_model_triangle_strips import create_models_triangle_strips
|
||||||
|
@ -14,7 +14,6 @@ from .msh_material import *
|
||||||
from .msh_material_gather import gather_materials
|
from .msh_material_gather import gather_materials
|
||||||
from .msh_material_utilities import remove_unused_materials
|
from .msh_material_utilities import remove_unused_materials
|
||||||
from .msh_utilities import *
|
from .msh_utilities import *
|
||||||
from .msh_anim_gather import *
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SceneAABB:
|
class SceneAABB:
|
||||||
|
@ -44,8 +43,6 @@ class Scene:
|
||||||
name: str = "Scene"
|
name: str = "Scene"
|
||||||
materials: Dict[str, Material] = field(default_factory=dict)
|
materials: Dict[str, Material] = field(default_factory=dict)
|
||||||
models: List[Model] = field(default_factory=list)
|
models: List[Model] = field(default_factory=list)
|
||||||
anims: List[Animation] = field(default_factory=list)
|
|
||||||
|
|
||||||
|
|
||||||
def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str) -> Scene:
|
def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str) -> Scene:
|
||||||
""" Create a msh Scene from the active Blender scene. """
|
""" Create a msh Scene from the active Blender scene. """
|
||||||
|
@ -70,24 +67,8 @@ def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_t
|
||||||
if has_multiple_root_models(scene.models):
|
if has_multiple_root_models(scene.models):
|
||||||
scene.models = reparent_model_roots(scene.models)
|
scene.models = reparent_model_roots(scene.models)
|
||||||
|
|
||||||
|
|
||||||
#now that we've collected all models, we should remap WGHT indices...
|
|
||||||
names_to_indices = {}
|
|
||||||
for i,model in enumerate(scene.models):
|
|
||||||
names_to_indices[model.name] = i;
|
|
||||||
|
|
||||||
for model in scene.models:
|
|
||||||
if model.model_type == ModelType.SKIN:
|
|
||||||
for segment in model.geometry:
|
|
||||||
for i in range(len(segment.weights)):
|
|
||||||
vgroup_index = segment.weights[i][0]
|
|
||||||
segment.weights[i][0] = names_to_indices[model.vgroups_to_modelnames_map[vgroup_index]]
|
|
||||||
|
|
||||||
|
|
||||||
scene.materials = remove_unused_materials(scene.materials, scene.models)
|
scene.materials = remove_unused_materials(scene.materials, scene.models)
|
||||||
|
|
||||||
#scene.anims = gather_animdata(bpy.context.scene.objects["Armature"])
|
|
||||||
|
|
||||||
return scene
|
return scene
|
||||||
|
|
||||||
def create_scene_aabb(scene: Scene) -> SceneAABB:
|
def create_scene_aabb(scene: Scene) -> SceneAABB:
|
||||||
|
|
|
@ -8,8 +8,6 @@ from .msh_material import *
|
||||||
from .msh_writer import Writer
|
from .msh_writer import Writer
|
||||||
from .msh_utilities import *
|
from .msh_utilities import *
|
||||||
|
|
||||||
from .crc import *
|
|
||||||
|
|
||||||
def save_scene(output_file, scene: Scene):
|
def save_scene(output_file, scene: Scene):
|
||||||
""" Saves scene to the supplied file. """
|
""" Saves scene to the supplied file. """
|
||||||
|
|
||||||
|
@ -26,11 +24,7 @@ def save_scene(output_file, scene: Scene):
|
||||||
|
|
||||||
for index, model in enumerate(scene.models):
|
for index, model in enumerate(scene.models):
|
||||||
with msh2.create_child("MODL") as modl:
|
with msh2.create_child("MODL") as modl:
|
||||||
_write_modl(modl, model, index, material_index, scene)
|
_write_modl(modl, model, index, material_index)
|
||||||
|
|
||||||
#with hedr.create_child("ANM2") as anm2: #simple for now
|
|
||||||
# for anim in scene.anims:
|
|
||||||
# _write_anm2(anm2, anim)
|
|
||||||
|
|
||||||
with hedr.create_child("CL1L"):
|
with hedr.create_child("CL1L"):
|
||||||
pass
|
pass
|
||||||
|
@ -40,8 +34,8 @@ def _write_sinf(sinf: Writer, scene: Scene):
|
||||||
name.write_string(scene.name)
|
name.write_string(scene.name)
|
||||||
|
|
||||||
with sinf.create_child("FRAM") as fram:
|
with sinf.create_child("FRAM") as fram:
|
||||||
fram.write_i32(0, 20) #test values
|
fram.write_i32(0, 1)
|
||||||
fram.write_f32(10.0) #test values
|
fram.write_f32(29.97003)
|
||||||
|
|
||||||
with sinf.create_child("BBOX") as bbox:
|
with sinf.create_child("BBOX") as bbox:
|
||||||
aabb = create_scene_aabb(scene)
|
aabb = create_scene_aabb(scene)
|
||||||
|
@ -103,7 +97,7 @@ def _write_matd(matd: Writer, material_name: str, material: Material):
|
||||||
with matd.create_child("TX3D") as tx3d:
|
with matd.create_child("TX3D") as tx3d:
|
||||||
tx3d.write_string(material.texture3)
|
tx3d.write_string(material.texture3)
|
||||||
|
|
||||||
def _write_modl(modl: Writer, model: Model, index: int, material_index: Dict[str, int], scene: Scene):
|
def _write_modl(modl: Writer, model: Model, index: int, material_index: Dict[str, int]):
|
||||||
with modl.create_child("MTYP") as mtyp:
|
with modl.create_child("MTYP") as mtyp:
|
||||||
mtyp.write_u32(model.model_type.value)
|
mtyp.write_u32(model.model_type.value)
|
||||||
|
|
||||||
|
@ -130,12 +124,6 @@ def _write_modl(modl: Writer, model: Model, index: int, material_index: Dict[str
|
||||||
with geom.create_child("SEGM") as segm:
|
with geom.create_child("SEGM") as segm:
|
||||||
_write_segm(segm, segment, material_index)
|
_write_segm(segm, segment, material_index)
|
||||||
|
|
||||||
if model.model_type == ModelType.SKIN:
|
|
||||||
with modl.create_child("ENVL") as envl:
|
|
||||||
envl.write_u32(len(scene.models))
|
|
||||||
for i in range(len(scene.models)):
|
|
||||||
envl.write_u32(i)
|
|
||||||
|
|
||||||
if model.collisionprimitive is not None:
|
if model.collisionprimitive is not None:
|
||||||
with modl.create_child("SWCI") as swci:
|
with modl.create_child("SWCI") as swci:
|
||||||
swci.write_u32(model.collisionprimitive.shape.value)
|
swci.write_u32(model.collisionprimitive.shape.value)
|
||||||
|
@ -165,13 +153,6 @@ def _write_segm(segm: Writer, segment: GeometrySegment, material_index: Dict[str
|
||||||
for normal in segment.normals:
|
for normal in segment.normals:
|
||||||
nrml.write_f32(normal.x, normal.y, normal.z)
|
nrml.write_f32(normal.x, normal.y, normal.z)
|
||||||
|
|
||||||
if segment.weights is not None:
|
|
||||||
with segm.create_child("WGHT") as wght:
|
|
||||||
wght.write_u32(len(segment.weights) / 4)
|
|
||||||
for weight in segment.weights:
|
|
||||||
wght.write_u32(weight[0])
|
|
||||||
wght.write_f32(weight[1])
|
|
||||||
|
|
||||||
if segment.colors is not None:
|
if segment.colors is not None:
|
||||||
with segm.create_child("CLRL") as clrl:
|
with segm.create_child("CLRL") as clrl:
|
||||||
clrl.write_u32(len(segment.colors))
|
clrl.write_u32(len(segment.colors))
|
||||||
|
@ -208,46 +189,3 @@ def _write_segm(segm: Writer, segment: GeometrySegment, material_index: Dict[str
|
||||||
|
|
||||||
for index in islice(strip, 2, len(strip)):
|
for index in islice(strip, 2, len(strip)):
|
||||||
strp.write_u16(index)
|
strp.write_u16(index)
|
||||||
|
|
||||||
|
|
||||||
def _write_anm2(anm2: Writer, anim: Animation):
|
|
||||||
|
|
||||||
with anm2.create_child("CYCL") as cycl:
|
|
||||||
|
|
||||||
cycl.write_u32(1)
|
|
||||||
cycl.write_string(anim.name)
|
|
||||||
|
|
||||||
for _ in range(63 - len(anim.name)):
|
|
||||||
cycl.write_u8(0)
|
|
||||||
|
|
||||||
cycl.write_f32(10.0) #test framerate
|
|
||||||
cycl.write_u32(0) #what does play style refer to?
|
|
||||||
cycl.write_u32(0, 20) #first frame indices
|
|
||||||
|
|
||||||
|
|
||||||
with anm2.create_child("KFR3") as kfr3:
|
|
||||||
|
|
||||||
kfr3.write_u32(len(anim.bone_transforms.keys()))
|
|
||||||
|
|
||||||
for boneName in anim.bone_transforms.keys():
|
|
||||||
kfr3.write_u32(crc(boneName))
|
|
||||||
kfr3.write_u32(0) #what is keyframe type?
|
|
||||||
|
|
||||||
kfr3.write_u32(21, 21) #basic testing
|
|
||||||
|
|
||||||
for i, xform in enumerate(anim.bone_transforms[boneName]):
|
|
||||||
kfr3.write_u32(i)
|
|
||||||
kfr3.write_f32(xform.translation.x, xform.translation.y, xform.translation.z)
|
|
||||||
|
|
||||||
for i, xform in enumerate(anim.bone_transforms[boneName]):
|
|
||||||
kfr3.write_u32(i)
|
|
||||||
kfr3.write_f32(xform.rotation.x, xform.rotation.y, xform.rotation.z, xform.rotation.w)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue