Salve pessoal, adaptei esse script para ler os arquivos .msh e .bon do WYD no blender 2.8 +, carregando a malha e os ossos, créditos a um amigo que me ajudou no entendimento da base desse conteúdo, não sei o nick dele na WC
para usar é muito simples, basta definir o caminho do arquivo .msh e do arquivo .bon correspondente, e também o caminho da textura em jpg ou png.
import bpy
import os
import struct
import logging
import mathutils
from typing import NamedTuple
FilePath = "C:\\......\\be010101.msh"
FileName = "be010101"
FilePathBon = "C:\\.......\\be01.bon"
IMAGEPATH = 'C:\\.........\\be010101.png'
print("----------------- Start Script -----------------")
class BoneNode:
def __init__(self, Owner, Children, Matrix):
self.Owner = Owner
self.Children = Children
self.Matrix = Matrix
class BoneData:
def __init__(self, dwName, Matrix):
self.dwName = dwName
self.Matrix = Matrix
class BoneWeight:
def __init__(self, b0Weight, b0Index, b1Weight, b1Index, b2Weight, b2Index, b3Weight, b3Index):
self.b0Weight = b0Weight
self.b0Index = b0Index
self.b1Weight = b1Weight
self.b1Index = b1Index
self.b2Weight = b2Weight
self.b2Index = b2Index
self.b3Weight = b3Weight
self.b3Index = b3Index
print ("---------------------Load Bon---------------------")
bNodes = []
TreeNodes = []
with open(FilePathBon, "rb") as binFileBone:
binFileBone.seek(0,os.SEEK_END)
binFileBoneSize = binFileBone.tell()
binFileBone.seek(0,os.SEEK_SET)
BytesRead = 0
while(BytesRead < binFileBoneSize):
Own = struct.unpack('i', binFileBone.read(4))[0]
Chd = struct.unpack('i', binFileBone.read(4))[0]
bNodes.append(BoneNode(Own,Chd, None))
BytesRead += 8
print("---------------------Load Mesh-------------------")
with open(FilePath, "rb") as file: # b is important -> binary
_dwParentID = struct.unpack('i', file.read(4))[0]
_dwID = struct.unpack('i', file.read(4))[0]
_dwFVF = struct.unpack('i', file.read(4))[0]
_sizeVertex = struct.unpack('i', file.read(4))[0]
_numFaceInflunce = struct.unpack('i', file.read(4))[0]
_numPalette = struct.unpack('i', file.read(4))[0]
_VertexCount = struct.unpack('i', file.read(4))[0]
_FaceCount = struct.unpack('i', file.read(4))[0]
_numFaces = int(_FaceCount / 3)
print("dwParent: ",_dwParentID)
print("_dwID: ",_dwID)
print("_dwFVF: ",_dwFVF)
print("_sizeVertex: ",_sizeVertex)
print("_numFaceInflunce: ",_numFaceInflunce)
print("_numPalette: ",_numPalette)
print("_VertexCount: ",_VertexCount)
print("_FaceCount: ", _FaceCount)
print("_numFaces: ",_numFaces)
lVertxPos = []
lNormalPos = []
lUvPos = []
lIndices = []
lBonesPos = []
ldwName = []
lBoneWeight = []
for i in range(0,_numPalette):
bMatrix = mathutils.Matrix().to_4x4()
bMatrix[0][0] = struct.unpack('f', file.read(4))[0]
bMatrix[1][0] = struct.unpack('f', file.read(4))[0]
bMatrix[2][0] = struct.unpack('f', file.read(4))[0]
bMatrix[3][0] = struct.unpack('f', file.read(4))[0]
bMatrix[0][1] = struct.unpack('f', file.read(4))[0]
bMatrix[1][1] = struct.unpack('f', file.read(4))[0]
bMatrix[2][1] = struct.unpack('f', file.read(4))[0]
bMatrix[3][1] = struct.unpack('f', file.read(4))[0]
bMatrix[0][2] = struct.unpack('f', file.read(4))[0]
bMatrix[1][2] = struct.unpack('f', file.read(4))[0]
bMatrix[2][2] = struct.unpack('f', file.read(4))[0]
bMatrix[3][2] = struct.unpack('f', file.read(4))[0]
bMatrix[0][3] = struct.unpack('f', file.read(4))[0]
bMatrix[1][3] = struct.unpack('f', file.read(4))[0]
bMatrix[2][3] = struct.unpack('f', file.read(4))[0]
bMatrix[3][3] = struct.unpack('f', file.read(4))[0]
bMatrix.invert()
'''print("Invert2:")
print(bMatrix)
print(loc, rot, sca)'''
loc, rot, sca = bMatrix.decompose()
'''loc.z = loc.z * - 1'''
bMatrix = mathutils.Matrix().LocRotScale(loc, rot, sca)
lBonesPos.append(BoneData(0, bMatrix))
for i in range(0,_numPalette):
dwName = struct.unpack('i', file.read(4))[0]
lBonesPos[i].dwName = dwName
print("dwName: ",dwName)
ldwName.append(dwName)
for i in range(0,_VertexCount):
vX = struct.unpack('f', file.read(4))[0]
vY = struct.unpack('f', file.read(4))[0]
vZ = struct.unpack('f', file.read(4))[0]
Vertex = (vX, vY, vZ)
if _numFaceInflunce == 4:
bweight0 = struct.unpack('f', file.read(4))[0]
bweight1 = struct.unpack('f', file.read(4))[0]
bweight2 = struct.unpack('f', file.read(4))[0]
bboneIndex0 = struct.unpack('b', file.read(1))[0]
bboneIndex1 = struct.unpack('b', file.read(1))[0]
bboneIndex2 = struct.unpack('b', file.read(1))[0]
struct.unpack('b', file.read(1))[0]
bw = BoneWeight(bweight0,bboneIndex0,bweight1,bboneIndex1,bweight2,bboneIndex2, 0, 0)
lBoneWeight.append(bw)
elif _numFaceInflunce == 3:
bweight0 = struct.unpack('f', file.read(4))[0]
bweight1 = struct.unpack('f', file.read(4))[0]
bboneIndex0 = struct.unpack('b', file.read(1))[0]
bboneIndex1 = struct.unpack('b', file.read(1))[0]
u1 = struct.unpack('b', file.read(1))[0]
u2 = struct.unpack('b', file.read(1))[0]
bw = BoneWeight(bweight0,bboneIndex0,bweight1,bboneIndex1,0, 0, 0, 0)
lBoneWeight.append(bw)
elif _numFaceInflunce == 2:
bweight0 = struct.unpack('f', file.read(4))[0]
bboneIndex0 = struct.unpack('b', file.read(1))[0]
struct.unpack('b', file.read(1))[0]
struct.unpack('b', file.read(1))[0]
struct.unpack('b', file.read(1))[0]
bw = BoneWeight(bweight0,bboneIndex0,0,0,0, 0, 0, 0)
lBoneWeight.append(bw)
else:
print("este arquivo possuie faceinfluence: ", _numFaceInflunce)
nX = struct.unpack('f', file.read(4))[0]
nY = struct.unpack('f', file.read(4))[0]
nZ = struct.unpack('f', file.read(4))[0]
Normal = (nX, nY, nZ)
uX = struct.unpack('f', file.read(4))[0]
uY = struct.unpack('f', file.read(4))[0]
uV = (uX,uY * -1)
lVertxPos.append(Vertex)
lNormalPos.append(Normal)
lUvPos.append(uV)
for i in range(0, _numFaces):
f1 = struct.unpack('H', file.read(2))[0]
f2 = struct.unpack('H', file.read(2))[0]
f3 = struct.unpack('H', file.read(2))[0]
triangulos = (f1, f2, f3)
lIndices.append(triangulos)
edge = []
new_mesh = bpy.data.meshes.new('mesh')
new_mesh.from_pydata(lVertxPos, edge, lIndices)
new_mesh.update()
obj_mesh = bpy.data.objects.new(FileName, new_mesh)
obj_mesh.data.normals_split_custom_set_from_vertices(lNormalPos)
obj_mesh.modifiers.new(name = 'Skeleton', type = 'ARMATURE')
'''Set UV'''
uvlayer = obj_mesh.data.uv_layers.new()
obj_mesh.data.uv_layers.active = uvlayer
pos = 0
for face in obj_mesh.data.polygons:
for vert_idx, loop_idx in zip(face.vertices, face.loop_indices):
uvlayer.data[loop_idx].uv = lUvPos[vert_idx]
pos += 1
'''mat = bpy.data.materials['Material']
tex = bpy.data.textures.new("SomeName", 'IMAGE')
slot = mat.texture_slots.add()
slot.texture = tex'''
amt = bpy.data.armatures.new('root')
Container = bpy.data.objects.new('Armature', amt)
obj_mesh.modifiers['Skeleton'].object = Container
'''obj_mesh.modifiers['Skeleton'].object = armt'''
# make collection
new_collection = bpy.data.collections.new('Loaded@'+FileName)
bpy.context.scene.collection.children.link(new_collection)
new_collection.objects.link(Container)
new_collection.objects.link(obj_mesh)
obj_mesh.parent = Container
bpy.context.view_layer.objects.active = Container
bpy.ops.object.mode_set(mode='EDIT')
print("-----------------Create Three Node-------------------")
class BoneTreeStruct:
def __init__(self, dwname, Fater, Bone,Owner,Children ):
self.dwname = dwname
self.Fater = Fater
self.Bone = Bone
self.Owner = Owner
self.Children = Children
ignoreCount = 0
for b in bNodes:
if ignoreCount > 0:
ignoreCount -= 1
continue
chk = BoneTreeStruct(0,0,None,0,0)
ischk = False
for tr in TreeNodes:
if tr.Owner == b.Children:
chk = tr
ischk = True
break
if ischk == False:
'''chk.Bone = bpy.data.objects.new(str(b.Children), None)'''
chk = BoneTreeStruct(b.Children,0, None,b.Children,0)
chk.Bone = amt.edit_bones.new(str(b.Children))
chk.Bone.head = (0,0,0)
chk.Bone.tail = (0,0,0.1)
TreeNodes.append(chk)
print("definindo filhos")
for fi in bNodes:
if fi.Owner == chk.Owner:
nFilho = BoneTreeStruct(fi.Children, chk,0,fi.Children,0)
'''nFilho.Bone = bpy.data.objects.new(str(fi.Children), None)'''
nFilho.Bone = amt.edit_bones.new(str(fi.Children))
nFilho.Bone.head = (0,0,0)
nFilho.Bone.tail = (0,0,0.1)
nFilho.Bone.parent = chk.Bone
TreeNodes.append(nFilho)
for bTree in TreeNodes:
print(bTree.Bone.name)
for dwInfo in lBonesPos:
if(int(dwInfo.dwName) == int(bTree.Bone.name)):
print("set matrix bone "+str(dwInfo.dwName))
bTree.Bone.matrix = dwInfo.Matrix
bpy.context.view_layer.objects.active = obj_mesh
vertexGroup = []
for i in range(0,_numPalette):
new_vertex_group = bpy.context.active_object.vertex_groups.new(name=str(lBonesPos[i].dwName))
vertexGroup.append(vertexGroup)
for i in range(0,_VertexCount):
if _numFaceInflunce == 4:
bpy.context.active_object.vertex_groups[lBoneWeight[i].b0Index].add([i], lBoneWeight[i].b0Weight, 'ADD')
bpy.context.active_object.vertex_groups[lBoneWeight[i].b1Index].add([i], lBoneWeight[i].b1Weight, 'ADD')
bpy.context.active_object.vertex_groups[lBoneWeight[i].b2Index].add([i], lBoneWeight[i].b2Weight, 'ADD')
elif _numFaceInflunce == 3:
bpy.context.active_object.vertex_groups[lBoneWeight[i].b0Index].add([i], lBoneWeight[i].b0Weight, 'ADD')
bpy.context.active_object.vertex_groups[lBoneWeight[i].b1Index].add([i], lBoneWeight[i].b1Weight, 'ADD')
elif _numFaceInflunce == 2:
bpy.context.active_object.vertex_groups[lBoneWeight[i].b0Index].add([i], lBoneWeight[i].b0Weight, 'ADD')
else:
print("este arquivo possuie faceinfluence: ", _numFaceInflunce)
mat = bpy.data.materials.new(name="New_Mat")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
texImage = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImage.image = bpy.data.images.load(IMAGEPATH)
mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage.outputs['Color'])
if obj_mesh.data.materials:
obj_mesh.data.materials[0] = mat
else:
obj_mesh.data.materials.append(mat)