Minor envelope progress
This commit is contained in:
parent
2599a7203e
commit
1892a1cdbd
|
@ -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.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]
|
||||
|
||||
|
||||
|
|
|
@ -34,11 +34,11 @@ class GeometrySegment:
|
|||
material_name: str = ""
|
||||
|
||||
positions: List[Vector] = field(default_factory=list)
|
||||
weights: List[Tuple[int, float]] = None
|
||||
normals: List[Vector] = field(default_factory=list)
|
||||
colors: List[List[float]] = None
|
||||
texcoords: List[Vector] = field(default_factory=list)
|
||||
# TODO: Skin support.
|
||||
|
||||
weights: List[Tuple[int, float]] = None
|
||||
|
||||
polygons: 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
|
||||
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"
|
||||
anim_type: str = "HardSkinned"
|
||||
bone_transforms: Dict[str, List[ModelTransform]] = field(default_factory=dict)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import bpy
|
||||
import math
|
||||
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 .msh_model 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()
|
||||
|
||||
models_list: List[Model] = []
|
||||
model_indices: Dict[str, int] = {}
|
||||
|
||||
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
|
||||
skeleton: bpy.types.Armature = None
|
||||
|
||||
for uneval_obj in select_objects(export_target):
|
||||
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.type == "ARMATURE":
|
||||
model.parent = obj.parent.parent.name
|
||||
else:
|
||||
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:
|
||||
mesh = obj.to_mesh()
|
||||
|
||||
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)
|
||||
mesh = obj.to_mesh()
|
||||
model.geometry = create_mesh_geometry(mesh, model.model_type == ModelType.SKIN)
|
||||
obj.to_mesh_clear()
|
||||
|
||||
_, _, 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)
|
||||
|
||||
|
||||
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
|
||||
|
||||
def create_parents_set() -> Set[str]:
|
||||
|
@ -94,7 +118,7 @@ def create_parents_set() -> Set[str]:
|
|||
|
||||
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.
|
||||
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:
|
||||
segment.colors = []
|
||||
|
||||
if vgrps_to_indices:
|
||||
for segment in segments:
|
||||
segment.weights = []
|
||||
|
||||
for segment, material in zip(segments, mesh.materials):
|
||||
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.normals.append(convert_vector_space(vertex_normal))
|
||||
|
||||
if vgrps_to_indices is not None:
|
||||
for i,grp_el in mesh.vertices[vertex_index].groups:
|
||||
segment.weights.append(tuple(vgrps_to_indices[grp_el.group], grp_el.weight))
|
||||
if i > 3:
|
||||
break
|
||||
while (i < 3):
|
||||
segment.weights.append(tuple(0,0.0))
|
||||
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:
|
||||
segment.texcoords.append(Vector((0.0, 0.0)))
|
||||
|
|
|
@ -46,6 +46,7 @@ class Scene:
|
|||
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:
|
||||
""" 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):
|
||||
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.anims = gather_animdata(bpy.context.scene.objects["Armature"])
|
||||
#scene.anims = gather_animdata(bpy.context.scene.objects["Armature"])
|
||||
|
||||
return scene
|
||||
|
||||
|
|
|
@ -26,11 +26,11 @@ def save_scene(output_file, scene: Scene):
|
|||
|
||||
for index, model in enumerate(scene.models):
|
||||
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
|
||||
for anim in scene.anims:
|
||||
_write_anm2(anm2, anim)
|
||||
#with hedr.create_child("ANM2") as anm2: #simple for now
|
||||
# for anim in scene.anims:
|
||||
# _write_anm2(anm2, anim)
|
||||
|
||||
with hedr.create_child("CL1L"):
|
||||
pass
|
||||
|
@ -103,7 +103,7 @@ def _write_matd(matd: Writer, material_name: str, material: Material):
|
|||
with matd.create_child("TX3D") as tx3d:
|
||||
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:
|
||||
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:
|
||||
with geom.create_child("SEGM") as segm:
|
||||
_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:
|
||||
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:
|
||||
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:
|
||||
with segm.create_child("CLRL") as clrl:
|
||||
clrl.write_u32(len(segment.colors))
|
||||
|
@ -207,7 +217,7 @@ def _write_anm2(anm2: Writer, anim: Animation):
|
|||
cycl.write_u32(1)
|
||||
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_f32(10.0) #test framerate
|
||||
|
|
Loading…
Reference in New Issue