mordify to export shape keys

This commit is contained in:
QuantumCoderQC 2021-10-18 20:00:06 +02:00
parent 3814cd9da7
commit d01c55fcd4

View file

@ -207,6 +207,14 @@ class ArmoryExporter:
return shape_keys return shape_keys
return None return None
@staticmethod
def get_morph_uv_index(mesh):
i = 0
for uv_layer in mesh.uv_layers:
if uv_layer.name == 'UVMap_shape_key':
return i
i +=1
def find_bone(self, name: str) -> Optional[Tuple[bpy.types.Bone, Dict]]: def find_bone(self, name: str) -> Optional[Tuple[bpy.types.Bone, Dict]]:
"""Finds the bone reference (a tuple containing the bone object """Finds the bone reference (a tuple containing the bone object
and its data) by the given name and returns it.""" and its data) by the given name and returns it."""
@ -1125,24 +1133,27 @@ class ArmoryExporter:
vert_pos = [] vert_pos = []
vert_nor = [] vert_nor = []
names = [] names = []
default_values = [] default_values = [0] * max_shape_keys
shape_key_base = bobject.data.shape_keys.key_blocks[0]
count = 0 count = 0
for shape_key in bobject.data.shape_keys.key_blocks: for shape_key in bobject.data.shape_keys.key_blocks[1:]:
if(count > max_shape_keys): if(count > max_shape_keys):
break break
vert_data = self.get_vertex_data_from_shape_key(shape_key) vert_data = self.get_vertex_data_from_shape_key(shape_key_base, shape_key)
vert_pos.append(vert_data['pos']) vert_pos.append(vert_data['pos'])
vert_nor.append(vert_data['nor']) vert_nor.append(vert_data['nor'])
names.append(shape_key.name) names.append(shape_key.name)
default_values.append(shape_key.value) default_values[count] = shape_key.value
count += 1 count += 1
min, max = self.bake_to_image(vert_pos, vert_nor, name, output_dir) min, max = self.bake_to_image(vert_pos, vert_nor, name, output_dir)
morph_target = {} morph_target = {}
morph_target['morph_target_data_file'] = name
morph_target['morph_target_ref'] = names morph_target['morph_target_ref'] = names
morph_target['morph_target_defaults'] = default_values morph_target['morph_target_defaults'] = default_values
morph_target['num_morph_targets'] = count morph_target['num_morph_targets'] = count
@ -1150,14 +1161,14 @@ class ArmoryExporter:
morph_target['morph_offset'] = min morph_target['morph_offset'] = min
out_mesh['morph_target'] = morph_target out_mesh['morph_target'] = morph_target
self.create_morph_uv_set(bobject)
return return
def get_vertex_data_from_shape_key(self, shape_key_data): def get_vertex_data_from_shape_key(self, shape_key_base, shape_key_data):
base_vert_pos = shape_key_base.data.values()
base_vert_nor = shape_key_base.normals_split_get()
vert_pos = shape_key_data.data.values() vert_pos = shape_key_data.data.values()
vert_nor = shape_key_data.normals_vertex_get() vert_nor = shape_key_data.normals_split_get()
num_verts = len(vert_pos) num_verts = len(vert_pos)
@ -1165,10 +1176,10 @@ class ArmoryExporter:
nor = [] nor = []
for i in range(num_verts): for i in range(num_verts):
pos.append(list(vert_pos[i].co)) pos.append(list(vert_pos[i].co - base_vert_pos[i].co))
temp = [] temp = []
for j in range(3): for j in range(3):
temp.append(vert_nor[j + i * 3]) temp.append(vert_nor[j + i * 3] - base_vert_nor[j + i * 3])
nor.append(temp) nor.append(temp)
return {'pos': pos, 'nor': nor} return {'pos': pos, 'nor': nor}
@ -1257,50 +1268,59 @@ class ArmoryExporter:
num_verts = len(loops) num_verts = len(loops)
num_uv_layers = len(exportMesh.uv_layers) num_uv_layers = len(exportMesh.uv_layers)
is_baked = self.has_baked_material(bobject, exportMesh.materials) is_baked = self.has_baked_material(bobject, exportMesh.materials)
self.has_shape_key = False
if('morph_target' in o):
self.has_shape_key = True
print(bobject.name)
print(self.has_shape_key)
has_tex = (self.get_export_uvs(bobject.data) and num_uv_layers > 0) or is_baked or self.has_shape_key
has_tex1 = has_tex and num_uv_layers > 1
print(has_tex)
print(has_tex1)
num_colors = len(exportMesh.vertex_colors) num_colors = len(exportMesh.vertex_colors)
has_col = self.get_export_vcols(bobject.data) and num_colors > 0 has_col = self.get_export_vcols(bobject.data) and num_colors > 0
# Check if shape keys were exported
has_morph_target = self.get_shape_keys(bobject.data) and not has_col
if(has_morph_target):
num_uv_layers -= 1
morph_uv_index = self.get_morph_uv_index(bobject.data)
has_tex = (self.get_export_uvs(bobject.data) and num_uv_layers > 0) or is_baked
has_tex1 = has_tex and num_uv_layers > 1
has_tang = self.has_tangents(bobject.data) has_tang = self.has_tangents(bobject.data)
pdata = np.empty(num_verts * 4, dtype='<f4') # p.xyz, n.z pdata = np.empty(num_verts * 4, dtype='<f4') # p.xyz, n.z
ndata = np.empty(num_verts * 2, dtype='<f4') # n.xy ndata = np.empty(num_verts * 2, dtype='<f4') # n.xy
if has_tex: if has_tex or has_morph_target:
t0map = 0 # Get active uvmap
t0data = np.empty(num_verts * 2, dtype='<f4')
uv_layers = exportMesh.uv_layers uv_layers = exportMesh.uv_layers
if uv_layers is not None:
if 'UVMap_baked' in uv_layers:
for i in range(0, len(uv_layers)):
if uv_layers[i].name == 'UVMap_baked':
t0map = i
break
else:
for i in range(0, len(uv_layers)):
if uv_layers[i].active_render:
t0map = i
break
if has_tex1:
t1map = 1 if t0map == 0 else 0
t1data = np.empty(num_verts * 2, dtype='<f4')
# Scale for packed coords
maxdim = 1.0 maxdim = 1.0
lay0 = uv_layers[t0map] if has_tex:
for v in lay0.data: t0map = 0 # Get active uvmap
if abs(v.uv[0]) > maxdim: t0data = np.empty(num_verts * 2, dtype='<f4')
maxdim = abs(v.uv[0]) if uv_layers is not None:
if abs(v.uv[1]) > maxdim: if 'UVMap_baked' in uv_layers:
maxdim = abs(v.uv[1]) for i in range(0, len(uv_layers)):
if has_tex1: if uv_layers[i].name == 'UVMap_baked':
lay1 = uv_layers[t1map] t0map = i
for v in lay1.data: break
else:
for i in range(0, len(uv_layers)):
if uv_layers[i].active_render and uv_layers[i].name is not 'UVMap_shape_key':
t0map = i
break
if has_tex1:
for i in range(0, len(uv_layers)):
if i is not t0map and uv_layers.name is not 'UVMap_shape_key':
t1map = i
t1data = np.empty(num_verts * 2, dtype='<f4')
# Scale for packed coords
lay0 = uv_layers[t0map]
for v in lay0.data:
if abs(v.uv[0]) > maxdim:
maxdim = abs(v.uv[0])
if abs(v.uv[1]) > maxdim:
maxdim = abs(v.uv[1])
if has_tex1:
lay1 = uv_layers[t1map]
for v in lay1.data:
if abs(v.uv[0]) > maxdim:
maxdim = abs(v.uv[0])
if abs(v.uv[1]) > maxdim:
maxdim = abs(v.uv[1])
if has_morph_target:
morph_data = np.empty(num_verts * 2, dtype='<f4')
lay2 = uv_layers[morph_uv_index]
for v in lay2.data:
if abs(v.uv[0]) > maxdim: if abs(v.uv[0]) > maxdim:
maxdim = abs(v.uv[0]) maxdim = abs(v.uv[0])
if abs(v.uv[1]) > maxdim: if abs(v.uv[1]) > maxdim:
@ -1342,6 +1362,8 @@ Make sure the mesh only has tris/quads.""")
lay0 = exportMesh.uv_layers[t0map] lay0 = exportMesh.uv_layers[t0map]
if has_tex1: if has_tex1:
lay1 = exportMesh.uv_layers[t1map] lay1 = exportMesh.uv_layers[t1map]
if has_morph_target:
lay2 = exportMesh.uv_layers[morph_uv_index]
if has_col: if has_col:
vcol0 = exportMesh.vertex_colors[0].data vcol0 = exportMesh.vertex_colors[0].data
@ -1372,6 +1394,10 @@ Make sure the mesh only has tris/quads.""")
tangdata[i3 ] = tang[0] tangdata[i3 ] = tang[0]
tangdata[i3 + 1] = tang[1] tangdata[i3 + 1] = tang[1]
tangdata[i3 + 2] = tang[2] tangdata[i3 + 2] = tang[2]
if has_morph_target:
uv = lay2.data[loop.index].uv
morph_data[i2 ] = uv[0]
morph_data[i2 + 1] = 1.0 - uv[1]
if has_col: if has_col:
col = vcol0[loop.index].color col = vcol0[loop.index].color
i3 = i * 3 i3 = i * 3
@ -1432,6 +1458,9 @@ Make sure the mesh only has tris/quads.""")
if has_tex1: if has_tex1:
t1data *= invscale_tex t1data *= invscale_tex
t1data = np.array(t1data, dtype='<i2') t1data = np.array(t1data, dtype='<i2')
if has_morph_target:
morph_data *= invscale_tex
morph_data = np.array(morph_data, dtype='<i2')
if has_col: if has_col:
cdata *= 32767 cdata *= 32767
cdata = np.array(cdata, dtype='<i2') cdata = np.array(cdata, dtype='<i2')
@ -1447,6 +1476,8 @@ Make sure the mesh only has tris/quads.""")
o['vertex_arrays'].append({ 'attrib': 'tex', 'values': t0data, 'data': 'short2norm' }) o['vertex_arrays'].append({ 'attrib': 'tex', 'values': t0data, 'data': 'short2norm' })
if has_tex1: if has_tex1:
o['vertex_arrays'].append({ 'attrib': 'tex1', 'values': t1data, 'data': 'short2norm' }) o['vertex_arrays'].append({ 'attrib': 'tex1', 'values': t1data, 'data': 'short2norm' })
if has_morph_target:
o['vertex_arrays'].append({ 'attrib': 'morph', 'values': morph_data, 'data': 'short2norm' })
if has_col: if has_col:
o['vertex_arrays'].append({ 'attrib': 'col', 'values': cdata, 'data': 'short4norm', 'padding': 1 }) o['vertex_arrays'].append({ 'attrib': 'col', 'values': cdata, 'data': 'short4norm', 'padding': 1 })
if has_tang: if has_tang:
@ -1538,12 +1569,18 @@ Make sure the mesh only has tris/quads.""")
shape_keys = ArmoryExporter.get_shape_keys(mesh) shape_keys = ArmoryExporter.get_shape_keys(mesh)
if shape_keys: if shape_keys:
# Save the morph state
active_shape_key_index = bobject.active_shape_key_index active_shape_key_index = bobject.active_shape_key_index
show_only_shape_key = bobject.show_only_shape_key show_only_shape_key = bobject.show_only_shape_key
current_morph_value = bobject.active_shape_key.value current_morph_value = bobject.active_shape_key.value
# Reset morph state to base for mesh export
bobject.active_shape_key_index = 0 bobject.active_shape_key_index = 0
bobject.show_only_shape_key = True bobject.show_only_shape_key = True
if self.get_export_vcols(bobject.data):
log.warn(oid + ' has vertex colors. Shape keys are not supported for objects with vertex colors')
shape_keys = False
else:
self.create_morph_uv_set(bobject)
self.depsgraph.update() self.depsgraph.update()
armature = bobject.find_armature() armature = bobject.find_armature()
@ -1553,13 +1590,7 @@ Make sure the mesh only has tris/quads.""")
export_mesh = bobject_eval.to_mesh() export_mesh = bobject_eval.to_mesh()
if shape_keys: if shape_keys:
if(len(bobject.data.uv_layers) > 2): self.export_shape_keys(bobject, export_mesh, out_mesh)
if(bobject.data.uv_layers.get('UVMap_shape_key') is not None):
self.export_shape_keys(bobject, export_mesh, out_mesh)
else:
log.warn(oid + ' has 2 or more UV Maps. Shape keys are not supported for objects with 2 or more UV maps')
else:
self.export_shape_keys(bobject, export_mesh, out_mesh)
if export_mesh is None: if export_mesh is None:
log.warn(oid + ' was not exported') log.warn(oid + ' was not exported')