Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #13 from griffon-9/NF4

NEW FEATURE (export_pmx / import_pmx) : BDEF4
  • Loading branch information...
commit 6d0bd09d7b6c7aa39977518ab2f5e84e9363cc64 2 parents 610150b + c89b16e
@ousttrue authored
View
48 blender26-meshio/export_pmx.py
@@ -13,7 +13,7 @@ def near(x, y, EPSILON=1e-5):
return d>=-EPSILON and d<=EPSILON
-def create_pmx(ex):
+def create_pmx(ex, enable_bdef4=True):
"""
PMX 出力
"""
@@ -25,6 +25,46 @@ def create_pmx(ex):
model.comment=o.get(bl.MMD_MB_COMMENT, 'Blnderエクスポート\n')
model.english_comment=o.get(bl.MMD_ENGLISH_COMMENT, 'blender export commen\n')
+ class DeformBuilder:
+ def __init__(self, skeleton):
+ self.skeleton=skeleton
+ self.bone_names={ b.name for b in skeleton.bones }
+ self.count_bdef1=0
+ self.count_bdef2=0
+ self.count_bdef4=0
+ self.count_error=0
+
+ def __filter(self, name, weight):
+ return name in self.bone_names
+
+ def __call__(self, ext_weight):
+ weights=[ (self.skeleton.indexByName(w[0]), w[1]) \
+ for w in ext_weight.get_normalized(4, self.__filter) ]
+ if len(weights)==0:
+ self.count_error+=1
+ return pmx.Bdef1(0) # Recovery
+ elif len(weights)==1:
+ self.count_bdef1+=1
+ return pmx.Bdef1(weights[0][0])
+ elif len(weights)==2:
+ self.count_bdef2+=1
+ return pmx.Bdef2(
+ weights[0][0], weights[1][0],
+ weights[0][1])
+ else:
+ if len(weights)==3:
+ weights.append( (0, 0.0) ) # Dummy Data
+ self.count_bdef4+=1
+ return pmx.Bdef4(
+ weights[0][0], weights[1][0], weights[2][0], weights[3][0],
+ weights[0][1], weights[1][1], weights[2][1], weights[3][1])
+
+ def show(self):
+ print("BDEF Statistics >>>")
+ print("\tBDEF1: %d BDEF2: %d BDEF4: %d ERROR: %d" % \
+ (self.count_bdef1, self.count_bdef2, self.count_bdef4, self.count_error))
+ deform_builder=DeformBuilder(ex.skeleton)
+
def get_deform(b0, b1, weight):
if b0==-1:
return pmx.Bdef1(b1, weight)
@@ -40,11 +80,15 @@ def get_deform(b0, b1, weight):
common.Vector3(attribute.nx, attribute.nz, attribute.ny),
# reverse vertical
common.Vector2(attribute.u, 1.0-attribute.v),
+ deform_builder(ext_weight) if enable_bdef4 else \
get_deform(ex.skeleton.indexByName(b0), ex.skeleton.indexByName(b1), weight),
# edge flag, 0: enable edge, 1: not edge
1.0
)
- for pos, attribute, b0, b1, weight in ex.oneSkinMesh.vertexArray.zip()]
+ for pos, attribute, b0, b1, weight, ext_weight in ex.oneSkinMesh.vertexArray.zip2()]
+
+ if enable_bdef4:
+ deform_builder.show()
boneMap=dict([(b.name, i) for i, b in enumerate(ex.skeleton.bones)])
View
8 blender26-meshio/exporter/oneskinmesh.py
@@ -367,6 +367,7 @@ def __mesh(self, obj):
weightMap, secondWeightMap=self.__getWeightMap(copyObj, copyMesh)
self.__processFaces(obj.name, copyMesh, weightMap, secondWeightMap)
+ self.__weights(copyObj, copyMesh, obj.name)
self.__skin(copyObj, obj.name)
bl.object.delete(copyObj)
@@ -469,5 +470,10 @@ def __getOrCreateMorph(self, name, type):
def getVertexCount(self):
return len(self.vertexArray.positions)
-
+ def __weights(self, obj, mesh, obj_name):
+ for v in mesh.vertices:
+ for i in self.vertexArray.getMappedIndex2(obj_name, v.index):
+ ext_w=self.vertexArray.ext_weight[i]
+ ext_w.entries.extend( filter( lambda ent: not ent[0].startswith("_"), \
+ ((obj.vertex_groups[vg.group].name, vg.weight) for vg in v.groups) ) )
View
34 blender26-meshio/exporter/vertexarray.py
@@ -42,6 +42,27 @@ def __hash__(self):
def __eq__(self, rhs):
return self.obj_index==rhs.obj_index and self.index==rhs.index
+class ExtendedWeights:
+ __slots__=[
+ 'entries'
+ ]
+
+ def __init__(self):
+ self.entries=[]
+
+ def each_entries(self, filter_func=lambda n, w: True):
+ for ent in self.entries:
+ if filter_func(*ent):
+ yield ent
+
+ def get_normalized(self, max_count=4, filter_func=lambda n, w: True):
+ import math
+ _entries=sorted(self.each_entries(filter_func), key=lambda ent: ent[1], reverse=True)
+ if len(_entries) > max_count:
+ _entries=_entries[0:max_count]
+ print("WARNING: Too many weights!")
+ total_weights=math.fsum(ent[1] for ent in _entries)
+ return ( (ent[0], ent[1]/total_weights if ent[1]>0.0 else 0.0) for ent in _entries )
class VertexArray(object):
"""
@@ -52,6 +73,7 @@ class VertexArray(object):
'positions',
'attributes', # normal and uv
'b0', 'b1', 'weight',
+ 'ext_weight',
'vertexMap',
'objectMap',
]
@@ -64,6 +86,7 @@ def __init__(self):
self.b0=[]
self.b1=[]
self.weight=[]
+ self.ext_weight=[]
self.vertexMap={}
self.objectMap={}
@@ -77,6 +100,11 @@ def zip(self):
self.positions, self.attributes,
self.b0, self.b1, self.weight)
+ def zip2(self):
+ return zip(
+ self.positions, self.attributes,
+ self.b0, self.b1, self.weight, self.ext_weight)
+
def each(self):
keys=[key for key in self.indexArrays.keys()]
keys.sort()
@@ -111,12 +139,18 @@ def __addVertex(self, vertexMapKey, pos, attribute, b0, b1, weight0):
self.b0.append(b0)
self.b1.append(b1)
self.weight.append(weight0)
+ self.ext_weight.append(ExtendedWeights())
assert(index<=65535)
return index
def getMappedIndex(self, obj_name, base_index):
return self.vertexMap[VertexKey(self.objectMap[obj_name], base_index)]
+ def getMappedIndex2(self, obj_name, base_index):
+ if obj_name not in self.objectMap:
+ return [ ] # Empty
+ return self.vertexMap.get(VertexKey(self.objectMap[obj_name], base_index), {}).values()
+
def addTriangle(self,
object_name, material,
base_index0, base_index1, base_index2,
View
9 blender26-meshio/import_pmx.py
@@ -518,6 +518,15 @@ def import_pmx_model(filepath, model, import_mesh, import_physics, **kwargs):
model.bones[v.deform.index0].name, i, v.deform.weight0)
bl.object.assignVertexGroup(mesh_object,
model.bones[v.deform.index1].name, i, 1.0-v.deform.weight0)
+ elif isinstance(v.deform, pmx.Bdef4):
+ bl.object.assignVertexGroup(mesh_object,
+ model.bones[v.deform.index0].name, i, v.deform.weight0)
+ bl.object.assignVertexGroup(mesh_object,
+ model.bones[v.deform.index1].name, i, v.deform.weight1)
+ bl.object.assignVertexGroup(mesh_object,
+ model.bones[v.deform.index2].name, i, v.deform.weight2)
+ bl.object.assignVertexGroup(mesh_object,
+ model.bones[v.deform.index3].name, i, v.deform.weight3)
else:
raise Exception("unknown deform: %s" % v.deform)
View
12 pymeshio/pmx/writer.py
@@ -60,9 +60,15 @@ def write_deform(self, deform):
self.write_bone_index(deform.index1)
self.write_float(deform.weight0)
elif isinstance(deform, pmx.Bdef4):
- # todo
- raise pymeshio.common.WriteException(
- "not implemented Bdef4")
+ self.write_int(2, 1)
+ self.write_bone_index(deform.index0)
+ self.write_bone_index(deform.index1)
+ self.write_bone_index(deform.index2)
+ self.write_bone_index(deform.index3)
+ self.write_float(deform.weight0)
+ self.write_float(deform.weight1)
+ self.write_float(deform.weight2)
+ self.write_float(deform.weight3)
else:
raise pymeshio.common.WriteException(
"unknown deform type: {0}".format(deform.type))
Please sign in to comment.
Something went wrong with that request. Please try again.