Minor envelope progress

This commit is contained in:
Will Snyder 2020-10-14 16:06:04 -04:00
parent 2599a7203e
commit 1892a1cdbd
5 changed files with 93 additions and 45 deletions

View File

@ -40,14 +40,14 @@ def gather_animdata(armature: bpy.types.Armature) -> List[Animation]:
xform.translation = Vector((vt.x * -1.0, vt.y, vt.z)) xform.translation = Vector((vt.x * -1.0, vt.y, vt.z))
xform.rotation = convert_rotation_space(bone.rotation_quaternion) xform.rotation = convert_rotation_space(bone.rotation_quaternion)
''' '''
xform.translation = bone.location xform.translation = bone.location
xform.rotation = bone.rotation_quaternion xform.rotation = bone.rotation_quaternion
anim_data.bone_transforms[bone.name].append(xform) anim_data.bone_transforms[bone.name].append(xform)
''' '''
return [anim_data] return [anim_data]

View File

@ -34,11 +34,11 @@ class GeometrySegment:
material_name: str = "" material_name: str = ""
positions: List[Vector] = field(default_factory=list) positions: List[Vector] = field(default_factory=list)
weights: List[Tuple[int, float]] = None
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)
@ -67,11 +67,12 @@ 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 @dataclass
class Animation: class Animation:
""" Class representing 'CYCL' + 'KFR3' sections in a .msh file """ """ Class representing 'CYCL' + 'KFR3' sections in a .msh file """
name: str = "open" name: str = "open"
anim_type: str = "HardSkinned"
bone_transforms: Dict[str, List[ModelTransform]] = field(default_factory=dict) bone_transforms: Dict[str, List[ModelTransform]] = field(default_factory=dict)

View File

@ -4,7 +4,7 @@
import bpy import bpy
import math import math
from enum import Enum from enum import Enum
from typing import List, Set, Dict, Tuple from typing import List, Set, Dict, Tuple, Set
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 *
@ -22,11 +22,7 @@ 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] = []
model_indices: Dict[str, int] = {} skeleton: bpy.types.Armature = None
for i, uneval_obj in enumerate(select_objects(export_target)):
if not (uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents):
model_indices[uneval_obj.name] = i
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:
@ -50,19 +46,23 @@ def gather_models(apply_modifiers: bool, export_target: str) -> List[Model]:
if obj.parent is not None: if obj.parent is not None:
if obj.parent.type == "ARMATURE": if obj.parent.type == "ARMATURE":
model.parent = obj.parent.parent.name skeleton = obj.parent
else:
model.parent = obj.parent.name 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)
vgroups_to_indices = {}
for i, vgroup in enumerate(obj.vertex_groups):
vgroups_to_indices[i] = model_indices[vgroup.name]
model.geometry = create_mesh_geometry(mesh, vgroups_to_indices)
obj.to_mesh_clear() obj.to_mesh_clear()
_, _, world_scale = obj.matrix_world.decompose() _, _, world_scale = obj.matrix_world.decompose()
@ -80,6 +80,30 @@ 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]:
@ -94,7 +118,7 @@ def create_parents_set() -> Set[str]:
return parents return parents
def create_mesh_geometry(mesh: bpy.types.Mesh, vgrps_to_indices : Dict[int, int]) -> List[GeometrySegment]: def create_mesh_geometry(mesh: bpy.types.Mesh, is_skinned : bool) -> 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. """
@ -115,10 +139,6 @@ def create_mesh_geometry(mesh: bpy.types.Mesh, vgrps_to_indices : Dict[int, int]
for segment in segments: for segment in segments:
segment.colors = [] segment.colors = []
if vgrps_to_indices:
for segment in segments:
segment.weights = []
for segment, material in zip(segments, mesh.materials): for segment, material in zip(segments, mesh.materials):
segment.material_name = material.name segment.material_name = material.name
@ -172,13 +192,15 @@ def create_mesh_geometry(mesh: bpy.types.Mesh, vgrps_to_indices : Dict[int, int]
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 vgrps_to_indices is not None: if is_skinned:
for i,grp_el in mesh.vertices[vertex_index].groups: for i,grp_el in mesh.vertices[vertex_index].groups:
segment.weights.append(tuple(vgrps_to_indices[grp_el.group], grp_el.weight)) segment.weights.append(tuple(grp_el.group, grp_el.weight))
if i > 3: print("Adding weight to group {grp_el.group} of value {grp_el.weight}")
break if i > 3: #will have to look into aramture/skin settings for limiting envolopes to 4 weights...
while (i < 3): break
segment.weights.append(tuple(0,0.0)) 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)))

View File

@ -46,6 +46,7 @@ class Scene:
models: List[Model] = field(default_factory=list) models: List[Model] = field(default_factory=list)
anims: List[Animation] = 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. """
@ -69,9 +70,23 @@ 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"]) #scene.anims = gather_animdata(bpy.context.scene.objects["Armature"])
return scene return scene

View File

@ -26,11 +26,11 @@ 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) _write_modl(modl, model, index, material_index, scene)
with hedr.create_child("ANM2") as anm2: #simple for now #with hedr.create_child("ANM2") as anm2: #simple for now
for anim in scene.anims: # for anim in scene.anims:
_write_anm2(anm2, anim) # _write_anm2(anm2, anim)
with hedr.create_child("CL1L"): with hedr.create_child("CL1L"):
pass pass
@ -103,7 +103,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]): def _write_modl(modl: Writer, model: Model, index: int, material_index: Dict[str, int], scene: Scene):
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)
@ -129,9 +129,12 @@ def _write_modl(modl: Writer, model: Model, index: int, material_index: Dict[str
for segment in model.geometry: for segment in model.geometry:
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.type = ModelType.SKIN:
with modl.create_child("ENVL") as envl: 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:
@ -162,6 +165,13 @@ 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))
@ -207,7 +217,7 @@ def _write_anm2(anm2: Writer, anim: Animation):
cycl.write_u32(1) cycl.write_u32(1)
cycl.write_string(anim.name) cycl.write_string(anim.name)
for _ in range(64 - (len(anim.name) + 1)): for _ in range(63 - len(anim.name)):
cycl.write_u8(0) cycl.write_u8(0)
cycl.write_f32(10.0) #test framerate cycl.write_f32(10.0) #test framerate