use with syntax to save file and fix no uv bug
This commit is contained in:
parent
40756b0178
commit
41d3c5f3b7
@ -64,235 +64,231 @@ def import_bm(context,filepath,externalTexture,blenderTempFolder):
|
|||||||
zipObj.extractall(tempFolder)
|
zipObj.extractall(tempFolder)
|
||||||
|
|
||||||
# index.bm
|
# index.bm
|
||||||
findex = open(os.path.join(tempFolder, "index.bm"), "rb")
|
|
||||||
# judge version first
|
|
||||||
gotten_version = read_uint32(findex)
|
|
||||||
if (gotten_version != bm_current_version):
|
|
||||||
utils.ShowMessageBox("Unsupported BM spec. Expect: {} Gotten: {}".format(bm_current_version, gotten_version), "Unsupported BM spec", 'WARNING')
|
|
||||||
findex.close()
|
|
||||||
tempFolderObj.cleanup()
|
|
||||||
return
|
|
||||||
objectList = []
|
objectList = []
|
||||||
meshList = []
|
meshList = []
|
||||||
materialList = []
|
materialList = []
|
||||||
textureList = []
|
textureList = []
|
||||||
while len(peek_stream(findex)) != 0:
|
with open(os.path.join(tempFolder, "index.bm"), "rb") as findex:
|
||||||
index_name = read_string(findex)
|
# judge version first
|
||||||
index_type = read_uint8(findex)
|
gotten_version = read_uint32(findex)
|
||||||
index_offset = read_uint64(findex)
|
if (gotten_version != bm_current_version):
|
||||||
blockCache = info_block_helper(index_name, index_offset)
|
utils.ShowMessageBox("Unsupported BM spec. Expect: {} Gotten: {}".format(bm_current_version, gotten_version), "Unsupported BM spec", 'WARNING')
|
||||||
if index_type == info_bm_type.OBJECT:
|
findex.close()
|
||||||
objectList.append(blockCache)
|
tempFolderObj.cleanup()
|
||||||
elif index_type == info_bm_type.MESH:
|
return
|
||||||
meshList.append(blockCache)
|
|
||||||
elif index_type == info_bm_type.MATERIAL:
|
while len(peek_stream(findex)) != 0:
|
||||||
materialList.append(blockCache)
|
index_name = read_string(findex)
|
||||||
elif index_type == info_bm_type.TEXTURE:
|
index_type = read_uint8(findex)
|
||||||
textureList.append(blockCache)
|
index_offset = read_uint64(findex)
|
||||||
else:
|
blockCache = info_block_helper(index_name, index_offset)
|
||||||
pass
|
if index_type == info_bm_type.OBJECT:
|
||||||
findex.close()
|
objectList.append(blockCache)
|
||||||
|
elif index_type == info_bm_type.MESH:
|
||||||
|
meshList.append(blockCache)
|
||||||
|
elif index_type == info_bm_type.MATERIAL:
|
||||||
|
materialList.append(blockCache)
|
||||||
|
elif index_type == info_bm_type.TEXTURE:
|
||||||
|
textureList.append(blockCache)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# texture.bm
|
# texture.bm
|
||||||
ftexture = open(os.path.join(tempFolder, "texture.bm"), "rb")
|
with open(os.path.join(tempFolder, "texture.bm"), "rb") as ftexture:
|
||||||
for item in textureList:
|
for item in textureList:
|
||||||
ftexture.seek(item.offset, os.SEEK_SET)
|
ftexture.seek(item.offset, os.SEEK_SET)
|
||||||
texture_filename = read_string(ftexture)
|
texture_filename = read_string(ftexture)
|
||||||
texture_isExternal = read_bool(ftexture)
|
texture_isExternal = read_bool(ftexture)
|
||||||
if texture_isExternal:
|
if texture_isExternal:
|
||||||
txur = load_image(texture_filename, externalTextureFolder)
|
txur = load_image(texture_filename, externalTextureFolder)
|
||||||
item.blenderData = txur
|
item.blenderData = txur
|
||||||
else:
|
else:
|
||||||
# not external. copy temp file into blender temp. then use it.
|
# not external. copy temp file into blender temp. then use it.
|
||||||
# try copy. if fail, don't need to do more
|
# try copy. if fail, don't need to do more
|
||||||
try:
|
try:
|
||||||
shutil.copy(os.path.join(tempTextureFolder, texture_filename), os.path.join(blenderTempTextureFolder, texture_filename))
|
shutil.copy(os.path.join(tempTextureFolder, texture_filename), os.path.join(blenderTempTextureFolder, texture_filename))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
txur = load_image(texture_filename, blenderTempTextureFolder)
|
txur = load_image(texture_filename, blenderTempTextureFolder)
|
||||||
item.blenderData = txur
|
item.blenderData = txur
|
||||||
txur.name = item.name
|
txur.name = item.name
|
||||||
|
|
||||||
ftexture.close()
|
|
||||||
|
|
||||||
# material.bm
|
# material.bm
|
||||||
fmaterial = open(os.path.join(tempFolder, "material.bm"), "rb")
|
with open(os.path.join(tempFolder, "material.bm"), "rb") as fmaterial:
|
||||||
for item in materialList:
|
for item in materialList:
|
||||||
fmaterial.seek(item.offset, os.SEEK_SET)
|
fmaterial.seek(item.offset, os.SEEK_SET)
|
||||||
|
|
||||||
# read data
|
# read data
|
||||||
material_colAmbient = read_3vector(fmaterial)
|
material_colAmbient = read_3vector(fmaterial)
|
||||||
material_colDiffuse = read_3vector(fmaterial)
|
material_colDiffuse = read_3vector(fmaterial)
|
||||||
material_colSpecular = read_3vector(fmaterial)
|
material_colSpecular = read_3vector(fmaterial)
|
||||||
material_colEmissive = read_3vector(fmaterial)
|
material_colEmissive = read_3vector(fmaterial)
|
||||||
material_specularPower = read_float(fmaterial)
|
material_specularPower = read_float(fmaterial)
|
||||||
material_useTexture = read_bool(fmaterial)
|
material_useTexture = read_bool(fmaterial)
|
||||||
material_texture = read_uint32(fmaterial)
|
material_texture = read_uint32(fmaterial)
|
||||||
|
|
||||||
# create basic material
|
# create basic material
|
||||||
m = bpy.data.materials.new(item.name)
|
m = bpy.data.materials.new(item.name)
|
||||||
m.use_nodes=True
|
m.use_nodes=True
|
||||||
for node in m.node_tree.nodes:
|
for node in m.node_tree.nodes:
|
||||||
m.node_tree.nodes.remove(node)
|
m.node_tree.nodes.remove(node)
|
||||||
bnode=m.node_tree.nodes.new(type="ShaderNodeBsdfPrincipled")
|
bnode=m.node_tree.nodes.new(type="ShaderNodeBsdfPrincipled")
|
||||||
mnode=m.node_tree.nodes.new(type="ShaderNodeOutputMaterial")
|
mnode=m.node_tree.nodes.new(type="ShaderNodeOutputMaterial")
|
||||||
m.node_tree.links.new(bnode.outputs[0],mnode.inputs[0])
|
m.node_tree.links.new(bnode.outputs[0],mnode.inputs[0])
|
||||||
|
|
||||||
m.metallic = sum(material_colAmbient) / 3
|
m.metallic = sum(material_colAmbient) / 3
|
||||||
m.diffuse_color = [i for i in material_colDiffuse] + [1]
|
m.diffuse_color = [i for i in material_colDiffuse] + [1]
|
||||||
m.specular_color = material_colSpecular
|
m.specular_color = material_colSpecular
|
||||||
m.specular_intensity = material_specularPower
|
m.specular_intensity = material_specularPower
|
||||||
|
|
||||||
# create a texture
|
# create a texture
|
||||||
if material_useTexture:
|
if material_useTexture:
|
||||||
inode=m.node_tree.nodes.new(type="ShaderNodeTexImage")
|
inode=m.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
inode.image=textureList[material_texture].blenderData
|
inode.image=textureList[material_texture].blenderData
|
||||||
m.node_tree.links.new(inode.outputs[0],bnode.inputs[0])
|
m.node_tree.links.new(inode.outputs[0],bnode.inputs[0])
|
||||||
|
|
||||||
# write custom property
|
# write custom property
|
||||||
m['virtools-ambient'] = material_colAmbient
|
m['virtools-ambient'] = material_colAmbient
|
||||||
m['virtools-diffuse'] = material_colDiffuse
|
m['virtools-diffuse'] = material_colDiffuse
|
||||||
m['virtools-specular'] = material_colSpecular
|
m['virtools-specular'] = material_colSpecular
|
||||||
m['virtools-emissive'] = material_colEmissive
|
m['virtools-emissive'] = material_colEmissive
|
||||||
m['virtools-power'] = material_specularPower
|
m['virtools-power'] = material_specularPower
|
||||||
|
|
||||||
item.blenderData = m
|
item.blenderData = m
|
||||||
|
|
||||||
fmaterial.close()
|
|
||||||
|
|
||||||
# mesh.bm
|
# mesh.bm
|
||||||
fmesh = open(os.path.join(tempFolder, "mesh.bm"), "rb")
|
with open(os.path.join(tempFolder, "mesh.bm"), "rb") as fmesh:
|
||||||
vList=[]
|
vList=[]
|
||||||
vtList=[]
|
vtList=[]
|
||||||
vnList=[]
|
vnList=[]
|
||||||
faceList=[]
|
faceList=[]
|
||||||
materialSolt = []
|
materialSolt = []
|
||||||
for item in meshList:
|
for item in meshList:
|
||||||
fmesh.seek(item.offset, os.SEEK_SET)
|
fmesh.seek(item.offset, os.SEEK_SET)
|
||||||
|
|
||||||
# create real mesh
|
# create real mesh
|
||||||
mesh = bpy.data.meshes.new(item.name)
|
mesh = bpy.data.meshes.new(item.name)
|
||||||
|
|
||||||
vList.clear()
|
vList.clear()
|
||||||
vtList.clear()
|
vtList.clear()
|
||||||
vnList.clear()
|
vnList.clear()
|
||||||
faceList.clear()
|
faceList.clear()
|
||||||
materialSolt.clear()
|
materialSolt.clear()
|
||||||
# in first read, store all data into list
|
# in first read, store all data into list
|
||||||
listCount = read_uint32(fmesh)
|
listCount = read_uint32(fmesh)
|
||||||
for i in range(listCount):
|
for i in range(listCount):
|
||||||
cache = read_3vector(fmesh)
|
cache = read_3vector(fmesh)
|
||||||
# switch yz
|
# switch yz
|
||||||
vList.append((cache[0], cache[2], cache[1]))
|
vList.append((cache[0], cache[2], cache[1]))
|
||||||
listCount = read_uint32(fmesh)
|
listCount = read_uint32(fmesh)
|
||||||
for i in range(listCount):
|
for i in range(listCount):
|
||||||
cache = read_2vector(fmesh)
|
cache = read_2vector(fmesh)
|
||||||
# reverse v
|
# reverse v
|
||||||
vtList.append((cache[0], -cache[1]))
|
vtList.append((cache[0], -cache[1]))
|
||||||
listCount = read_uint32(fmesh)
|
listCount = read_uint32(fmesh)
|
||||||
for i in range(listCount):
|
for i in range(listCount):
|
||||||
cache = read_3vector(fmesh)
|
cache = read_3vector(fmesh)
|
||||||
# switch yz
|
# switch yz
|
||||||
vnList.append((cache[0], cache[2], cache[1]))
|
vnList.append((cache[0], cache[2], cache[1]))
|
||||||
|
|
||||||
listCount = read_uint32(fmesh)
|
listCount = read_uint32(fmesh)
|
||||||
for i in range(listCount):
|
for i in range(listCount):
|
||||||
faceData = read_face(fmesh)
|
faceData = read_face(fmesh)
|
||||||
mesh_useMaterial = read_bool(fmesh)
|
mesh_useMaterial = read_bool(fmesh)
|
||||||
mesh_materialIndex = read_uint32(fmesh)
|
mesh_materialIndex = read_uint32(fmesh)
|
||||||
|
|
||||||
if mesh_useMaterial:
|
if mesh_useMaterial:
|
||||||
neededMaterial = materialList[mesh_materialIndex].blenderData
|
neededMaterial = materialList[mesh_materialIndex].blenderData
|
||||||
if neededMaterial in materialSolt:
|
if neededMaterial in materialSolt:
|
||||||
neededIndex = materialSolt.index(neededMaterial)
|
neededIndex = materialSolt.index(neededMaterial)
|
||||||
|
else:
|
||||||
|
neededIndex = len(materialSolt)
|
||||||
|
materialSolt.append(neededMaterial)
|
||||||
else:
|
else:
|
||||||
neededIndex = len(materialSolt)
|
neededIndex = -1
|
||||||
materialSolt.append(neededMaterial)
|
|
||||||
else:
|
|
||||||
neededIndex = -1
|
|
||||||
|
|
||||||
# we need invert triangle sort
|
# we need invert triangle sort
|
||||||
faceList.append((
|
faceList.append((
|
||||||
faceData[6], faceData[7], faceData[8],
|
faceData[6], faceData[7], faceData[8],
|
||||||
faceData[3], faceData[4], faceData[5],
|
faceData[3], faceData[4], faceData[5],
|
||||||
faceData[0], faceData[1], faceData[2],
|
faceData[0], faceData[1], faceData[2],
|
||||||
neededIndex
|
neededIndex
|
||||||
))
|
))
|
||||||
|
|
||||||
# and then we need add material solt for this mesh
|
# and then we need add material solt for this mesh
|
||||||
for mat in materialSolt:
|
for mat in materialSolt:
|
||||||
mesh.materials.append(mat)
|
mesh.materials.append(mat)
|
||||||
|
|
||||||
# then, we need add correspond count for vertices
|
# then, we need add correspond count for vertices
|
||||||
mesh.vertices.add(len(vList))
|
mesh.vertices.add(len(vList))
|
||||||
mesh.loops.add(len(faceList)*3) # triangle face confirm
|
mesh.loops.add(len(faceList)*3) # triangle face confirm
|
||||||
mesh.polygons.add(len(faceList))
|
mesh.polygons.add(len(faceList))
|
||||||
mesh.uv_layers.new(do_init=False)
|
mesh.uv_layers.new(do_init=False)
|
||||||
mesh.create_normals_split()
|
mesh.create_normals_split()
|
||||||
|
|
||||||
# add vertices data
|
# add vertices data
|
||||||
mesh.vertices.foreach_set("co", unpack_list(vList))
|
mesh.vertices.foreach_set("co", unpack_list(vList))
|
||||||
mesh.loops.foreach_set("vertex_index", unpack_list(flat_vertices_index(faceList)))
|
mesh.loops.foreach_set("vertex_index", unpack_list(flat_vertices_index(faceList)))
|
||||||
mesh.loops.foreach_set("normal", unpack_list(flat_vertices_normal(faceList, vnList)))
|
mesh.loops.foreach_set("normal", unpack_list(flat_vertices_normal(faceList, vnList)))
|
||||||
mesh.uv_layers[0].data.foreach_set("uv", unpack_list(flat_vertices_uv(faceList, vtList)))
|
mesh.uv_layers[0].data.foreach_set("uv", unpack_list(flat_vertices_uv(faceList, vtList)))
|
||||||
for i in range(len(faceList)):
|
for i in range(len(faceList)):
|
||||||
mesh.polygons[i].loop_start = i * 3
|
mesh.polygons[i].loop_start = i * 3
|
||||||
mesh.polygons[i].loop_total = 3
|
mesh.polygons[i].loop_total = 3
|
||||||
if faceList[i][9] != -1:
|
if faceList[i][9] != -1:
|
||||||
mesh.polygons[i].material_index = faceList[i][9]
|
mesh.polygons[i].material_index = faceList[i][9]
|
||||||
|
|
||||||
mesh.polygons[i].use_smooth = True
|
mesh.polygons[i].use_smooth = True
|
||||||
|
|
||||||
mesh.validate(clean_customdata=False)
|
mesh.validate(clean_customdata=False)
|
||||||
mesh.update(calc_edges=False, calc_edges_loose=False)
|
mesh.update(calc_edges=False, calc_edges_loose=False)
|
||||||
|
|
||||||
# add into item using
|
# add into item using
|
||||||
item.blenderData = mesh
|
item.blenderData = mesh
|
||||||
|
|
||||||
fmesh.close()
|
|
||||||
|
|
||||||
# object
|
# object
|
||||||
fobject = open(os.path.join(tempFolder, "object.bm"), "rb")
|
with open(os.path.join(tempFolder, "object.bm"), "rb") as fobject:
|
||||||
|
|
||||||
# we need get needed collection first
|
# we need get needed collection first
|
||||||
view_layer = context.view_layer
|
view_layer = context.view_layer
|
||||||
collection = view_layer.active_layer_collection.collection
|
collection = view_layer.active_layer_collection.collection
|
||||||
if prefs.no_component_collection == "":
|
if prefs.no_component_collection == "":
|
||||||
forcedCollection = None
|
forcedCollection = None
|
||||||
else:
|
|
||||||
try:
|
|
||||||
forcedCollection = bpy.data.collections[prefs.no_component_collection]
|
|
||||||
except:
|
|
||||||
forcedCollection = bpy.data.collections.new(prefs.no_component_collection)
|
|
||||||
view_layer.active_layer_collection.collection.children.link(forcedCollection)
|
|
||||||
|
|
||||||
# start process it
|
|
||||||
for item in objectList:
|
|
||||||
fobject.seek(item.offset, os.SEEK_SET)
|
|
||||||
|
|
||||||
# read data
|
|
||||||
object_isComponent = read_bool(fobject)
|
|
||||||
object_isForcedNoComponent = read_bool(fobject)
|
|
||||||
object_isHidden = read_bool(fobject)
|
|
||||||
object_worldMatrix = read_worldMaterix(fobject)
|
|
||||||
object_meshIndex = read_uint32(fobject)
|
|
||||||
|
|
||||||
# got mesh first
|
|
||||||
if object_isComponent:
|
|
||||||
neededMesh = load_component(object_meshIndex)
|
|
||||||
else:
|
else:
|
||||||
neededMesh = meshList[object_meshIndex].blenderData
|
try:
|
||||||
|
forcedCollection = bpy.data.collections[prefs.no_component_collection]
|
||||||
|
except:
|
||||||
|
forcedCollection = bpy.data.collections.new(prefs.no_component_collection)
|
||||||
|
view_layer.active_layer_collection.collection.children.link(forcedCollection)
|
||||||
|
|
||||||
# create real object
|
# start process it
|
||||||
obj = bpy.data.objects.new(item.name, neededMesh)
|
for item in objectList:
|
||||||
if (not object_isComponent) and object_isForcedNoComponent and (forcedCollection is not None):
|
fobject.seek(item.offset, os.SEEK_SET)
|
||||||
forcedCollection.objects.link(obj)
|
|
||||||
else:
|
# read data
|
||||||
collection.objects.link(obj)
|
object_isComponent = read_bool(fobject)
|
||||||
obj.matrix_world = object_worldMatrix
|
object_isForcedNoComponent = read_bool(fobject)
|
||||||
obj.hide_set(object_isHidden)
|
object_isHidden = read_bool(fobject)
|
||||||
|
object_worldMatrix = read_worldMaterix(fobject)
|
||||||
|
object_meshIndex = read_uint32(fobject)
|
||||||
|
|
||||||
|
# got mesh first
|
||||||
|
if object_isComponent:
|
||||||
|
neededMesh = load_component(object_meshIndex)
|
||||||
|
else:
|
||||||
|
neededMesh = meshList[object_meshIndex].blenderData
|
||||||
|
|
||||||
|
# create real object
|
||||||
|
obj = bpy.data.objects.new(item.name, neededMesh)
|
||||||
|
if (not object_isComponent) and object_isForcedNoComponent and (forcedCollection is not None):
|
||||||
|
forcedCollection.objects.link(obj)
|
||||||
|
else:
|
||||||
|
collection.objects.link(obj)
|
||||||
|
obj.matrix_world = object_worldMatrix
|
||||||
|
obj.hide_set(object_isHidden)
|
||||||
|
|
||||||
fobject.close()
|
|
||||||
view_layer.update()
|
view_layer.update()
|
||||||
|
|
||||||
tempFolderObj.cleanup()
|
tempFolderObj.cleanup()
|
||||||
@ -320,257 +316,252 @@ def export_bm(context,filepath,export_mode, export_target):
|
|||||||
forcedCollection = None
|
forcedCollection = None
|
||||||
|
|
||||||
# ============================================ export
|
# ============================================ export
|
||||||
finfo = open(os.path.join(tempFolder, "index.bm"), "wb")
|
with open(os.path.join(tempFolder, "index.bm"), "wb") as finfo:
|
||||||
write_uint32(finfo, bm_current_version)
|
write_uint32(finfo, bm_current_version)
|
||||||
|
|
||||||
# ====================== export object
|
# ====================== export object
|
||||||
fobject = open(os.path.join(tempFolder, "object.bm"), "wb")
|
meshSet = set()
|
||||||
meshSet = set()
|
meshList = []
|
||||||
meshList = []
|
meshCount = 0
|
||||||
meshCount = 0
|
with open(os.path.join(tempFolder, "object.bm"), "wb") as fobject:
|
||||||
for obj in objectList:
|
for obj in objectList:
|
||||||
# only export mesh object
|
# only export mesh object
|
||||||
if obj.type != 'MESH':
|
if obj.type != 'MESH':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# clean no mesh object
|
# clean no mesh object
|
||||||
currentMesh = obj.data
|
currentMesh = obj.data
|
||||||
if currentMesh is None:
|
if currentMesh is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# judge component
|
# judge component
|
||||||
object_isComponent = is_component(obj.name)
|
object_isComponent = is_component(obj.name)
|
||||||
object_isForcedNoComponent = False
|
object_isForcedNoComponent = False
|
||||||
if (forcedCollection is not None) and (obj.name in forcedCollection.objects):
|
if (forcedCollection is not None) and (obj.name in forcedCollection.objects):
|
||||||
# change it to forced no component
|
# change it to forced no component
|
||||||
object_isComponent = False
|
object_isComponent = False
|
||||||
object_isForcedNoComponent = True
|
object_isForcedNoComponent = True
|
||||||
|
|
||||||
# triangle first and then group
|
# triangle first and then group
|
||||||
if not object_isComponent:
|
if not object_isComponent:
|
||||||
if currentMesh not in meshSet:
|
if currentMesh not in meshSet:
|
||||||
mesh_triangulate(currentMesh)
|
mesh_triangulate(currentMesh)
|
||||||
meshSet.add(currentMesh)
|
meshSet.add(currentMesh)
|
||||||
meshList.append(currentMesh)
|
meshList.append(currentMesh)
|
||||||
meshId = meshCount
|
meshId = meshCount
|
||||||
meshCount += 1
|
meshCount += 1
|
||||||
else:
|
|
||||||
meshId = meshList.index(currentMesh)
|
|
||||||
else:
|
|
||||||
meshId = get_component_id(obj.name)
|
|
||||||
|
|
||||||
# get visibility
|
|
||||||
object_isHidden = not obj.visible_get()
|
|
||||||
|
|
||||||
# write finfo first
|
|
||||||
write_string(finfo, obj.name)
|
|
||||||
write_uint8(finfo, info_bm_type.OBJECT)
|
|
||||||
write_uint64(finfo, fobject.tell())
|
|
||||||
|
|
||||||
# write fobject
|
|
||||||
write_bool(fobject, object_isComponent)
|
|
||||||
write_bool(fobject, object_isForcedNoComponent)
|
|
||||||
print(object_isHidden)
|
|
||||||
write_bool(fobject, object_isHidden)
|
|
||||||
write_worldMatrix(fobject, obj.matrix_world)
|
|
||||||
write_uint32(fobject, meshId)
|
|
||||||
|
|
||||||
fobject.close()
|
|
||||||
|
|
||||||
# ====================== export mesh
|
|
||||||
fmesh = open(os.path.join(tempFolder, "mesh.bm"), "wb")
|
|
||||||
materialSet = set()
|
|
||||||
materialList = []
|
|
||||||
for mesh in meshList:
|
|
||||||
mesh.calc_normals_split()
|
|
||||||
|
|
||||||
# write finfo first
|
|
||||||
write_string(finfo, mesh.name)
|
|
||||||
write_uint8(finfo, info_bm_type.MESH)
|
|
||||||
write_uint64(finfo, fmesh.tell())
|
|
||||||
|
|
||||||
# write fmesh
|
|
||||||
# vertices
|
|
||||||
vecList = mesh.vertices[:]
|
|
||||||
write_uint32(fmesh, len(vecList))
|
|
||||||
for vec in vecList:
|
|
||||||
#swap yz
|
|
||||||
write_3vector(fmesh,vec.co[0],vec.co[2],vec.co[1])
|
|
||||||
|
|
||||||
# uv
|
|
||||||
face_index_pairs = [(face, index) for index, face in enumerate(mesh.polygons)]
|
|
||||||
uv_layer = mesh.uv_layers.active.data[:]
|
|
||||||
write_uint32(fmesh, len(face_index_pairs) * 3)
|
|
||||||
for f, f_index in face_index_pairs:
|
|
||||||
# it should be triangle face, otherwise throw a error
|
|
||||||
if (f.loop_total != 3):
|
|
||||||
raise Exception("Not a triangle", f.poly.loop_total)
|
|
||||||
|
|
||||||
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
|
||||||
uv = uv_layer[loop_index].uv
|
|
||||||
# reverse v
|
|
||||||
write_2vector(fmesh, uv[0], -uv[1])
|
|
||||||
|
|
||||||
# normals
|
|
||||||
write_uint32(fmesh, len(face_index_pairs) * 3)
|
|
||||||
for f, f_index in face_index_pairs:
|
|
||||||
# no need to check triangle again
|
|
||||||
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
|
||||||
nml = mesh.loops[loop_index].normal
|
|
||||||
# swap yz
|
|
||||||
write_3vector(fmesh, nml[0], nml[2], nml[1])
|
|
||||||
|
|
||||||
# face
|
|
||||||
# get material first
|
|
||||||
currentMat = mesh.materials[:]
|
|
||||||
noMaterial = len(currentMat) == 0
|
|
||||||
for mat in currentMat:
|
|
||||||
if mat not in materialSet:
|
|
||||||
materialSet.add(mat)
|
|
||||||
materialList.append(mat)
|
|
||||||
|
|
||||||
write_uint32(fmesh, len(face_index_pairs))
|
|
||||||
vtIndex = []
|
|
||||||
vnIndex = []
|
|
||||||
vIndex = []
|
|
||||||
for f, f_index in face_index_pairs:
|
|
||||||
# confirm material use
|
|
||||||
if noMaterial:
|
|
||||||
usedMat = 0
|
|
||||||
else:
|
|
||||||
usedMat = materialList.index(currentMat[f.material_index])
|
|
||||||
|
|
||||||
# export face
|
|
||||||
vtIndex.clear()
|
|
||||||
vnIndex.clear()
|
|
||||||
vIndex.clear()
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
|
||||||
vIndex.append(mesh.loops[loop_index].vertex_index)
|
|
||||||
vnIndex.append(f_index * 3 + counter)
|
|
||||||
vtIndex.append(f_index * 3 + counter)
|
|
||||||
counter += 1
|
|
||||||
# reverse vertices sort
|
|
||||||
write_face(fmesh,
|
|
||||||
vIndex[2], vtIndex[2], vnIndex[2],
|
|
||||||
vIndex[1], vtIndex[1], vnIndex[1],
|
|
||||||
vIndex[0], vtIndex[0], vnIndex[0])
|
|
||||||
|
|
||||||
# set used material
|
|
||||||
write_bool(fmesh, not noMaterial)
|
|
||||||
write_uint32(fmesh, usedMat)
|
|
||||||
|
|
||||||
mesh.free_normals_split()
|
|
||||||
|
|
||||||
fmesh.close()
|
|
||||||
|
|
||||||
# ====================== export material
|
|
||||||
fmaterial = open(os.path.join(tempFolder, "material.bm"), "wb")
|
|
||||||
textureSet = set()
|
|
||||||
textureList = []
|
|
||||||
textureCount = 0
|
|
||||||
for material in materialList:
|
|
||||||
# write finfo first
|
|
||||||
write_string(finfo, material.name)
|
|
||||||
write_uint8(finfo, info_bm_type.MATERIAL)
|
|
||||||
write_uint64(finfo, fmaterial.tell())
|
|
||||||
|
|
||||||
# try get original written data
|
|
||||||
material_colAmbient = try_get_custom_property(material, 'virtools-ambient')
|
|
||||||
material_colDiffuse = try_get_custom_property(material, 'virtools-diffuse')
|
|
||||||
material_colSpecular = try_get_custom_property(material, 'virtools-specular')
|
|
||||||
material_colEmissive = try_get_custom_property(material, 'virtools-emissive')
|
|
||||||
material_specularPower = try_get_custom_property(material, 'virtools-power')
|
|
||||||
|
|
||||||
# get basic color
|
|
||||||
mat_wrap = node_shader_utils.PrincipledBSDFWrapper(material)
|
|
||||||
if mat_wrap:
|
|
||||||
use_mirror = mat_wrap.metallic != 0.0
|
|
||||||
if use_mirror:
|
|
||||||
material_colAmbient = set_value_when_none(material_colAmbient, (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
|
|
||||||
else:
|
|
||||||
material_colAmbient = set_value_when_none(material_colAmbient, (1.0, 1.0, 1.0))
|
|
||||||
material_colDiffuse = set_value_when_none(material_colDiffuse, (mat_wrap.base_color[0], mat_wrap.base_color[1], mat_wrap.base_color[2]))
|
|
||||||
material_colSpecular = set_value_when_none(material_colSpecular, (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular))
|
|
||||||
material_colEmissive = set_value_when_none(material_colEmissive, mat_wrap.emission_color[:3])
|
|
||||||
material_specularPower = set_value_when_none(material_specularPower, 0.0)
|
|
||||||
|
|
||||||
# confirm texture
|
|
||||||
tex_wrap = getattr(mat_wrap, "base_color_texture", None)
|
|
||||||
if tex_wrap:
|
|
||||||
image = tex_wrap.image
|
|
||||||
if image:
|
|
||||||
# add into texture list
|
|
||||||
if image not in textureSet:
|
|
||||||
textureSet.add(image)
|
|
||||||
textureList.append(image)
|
|
||||||
currentTexture = textureCount
|
|
||||||
textureCount += 1
|
|
||||||
else:
|
else:
|
||||||
currentTexture = textureList.index(image)
|
meshId = meshList.index(currentMesh)
|
||||||
|
|
||||||
material_useTexture = True
|
|
||||||
material_texture = currentTexture
|
|
||||||
else:
|
else:
|
||||||
# no texture
|
meshId = get_component_id(obj.name)
|
||||||
|
|
||||||
|
# get visibility
|
||||||
|
object_isHidden = not obj.visible_get()
|
||||||
|
|
||||||
|
# write finfo first
|
||||||
|
write_string(finfo, obj.name)
|
||||||
|
write_uint8(finfo, info_bm_type.OBJECT)
|
||||||
|
write_uint64(finfo, fobject.tell())
|
||||||
|
|
||||||
|
# write fobject
|
||||||
|
write_bool(fobject, object_isComponent)
|
||||||
|
write_bool(fobject, object_isForcedNoComponent)
|
||||||
|
print(object_isHidden)
|
||||||
|
write_bool(fobject, object_isHidden)
|
||||||
|
write_worldMatrix(fobject, obj.matrix_world)
|
||||||
|
write_uint32(fobject, meshId)
|
||||||
|
|
||||||
|
# ====================== export mesh
|
||||||
|
materialSet = set()
|
||||||
|
materialList = []
|
||||||
|
with open(os.path.join(tempFolder, "mesh.bm"), "wb") as fmesh:
|
||||||
|
for mesh in meshList:
|
||||||
|
mesh.calc_normals_split()
|
||||||
|
|
||||||
|
# write finfo first
|
||||||
|
write_string(finfo, mesh.name)
|
||||||
|
write_uint8(finfo, info_bm_type.MESH)
|
||||||
|
write_uint64(finfo, fmesh.tell())
|
||||||
|
|
||||||
|
# write fmesh
|
||||||
|
# vertices
|
||||||
|
vecList = mesh.vertices[:]
|
||||||
|
write_uint32(fmesh, len(vecList))
|
||||||
|
for vec in vecList:
|
||||||
|
#swap yz
|
||||||
|
write_3vector(fmesh,vec.co[0],vec.co[2],vec.co[1])
|
||||||
|
|
||||||
|
# uv
|
||||||
|
face_index_pairs = [(face, index) for index, face in enumerate(mesh.polygons)]
|
||||||
|
write_uint32(fmesh, len(face_index_pairs) * 3)
|
||||||
|
if mesh.uv_layers.active is not None:
|
||||||
|
uv_layer = mesh.uv_layers.active.data[:]
|
||||||
|
for f, f_index in face_index_pairs:
|
||||||
|
# it should be triangle face, otherwise throw a error
|
||||||
|
if (f.loop_total != 3):
|
||||||
|
raise Exception("Not a triangle", f.poly.loop_total)
|
||||||
|
|
||||||
|
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
||||||
|
uv = uv_layer[loop_index].uv
|
||||||
|
# reverse v
|
||||||
|
write_2vector(fmesh, uv[0], -uv[1])
|
||||||
|
else:
|
||||||
|
# no uv data. write garbage
|
||||||
|
for i in range(len(face_index_pairs) * 3):
|
||||||
|
write_2vector(fmesh, 0.0, 0.0)
|
||||||
|
|
||||||
|
# normals
|
||||||
|
write_uint32(fmesh, len(face_index_pairs) * 3)
|
||||||
|
for f, f_index in face_index_pairs:
|
||||||
|
# no need to check triangle again
|
||||||
|
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
||||||
|
nml = mesh.loops[loop_index].normal
|
||||||
|
# swap yz
|
||||||
|
write_3vector(fmesh, nml[0], nml[2], nml[1])
|
||||||
|
|
||||||
|
# face
|
||||||
|
# get material first
|
||||||
|
currentMat = mesh.materials[:]
|
||||||
|
noMaterial = len(currentMat) == 0
|
||||||
|
for mat in currentMat:
|
||||||
|
if mat not in materialSet:
|
||||||
|
materialSet.add(mat)
|
||||||
|
materialList.append(mat)
|
||||||
|
|
||||||
|
write_uint32(fmesh, len(face_index_pairs))
|
||||||
|
vtIndex = []
|
||||||
|
vnIndex = []
|
||||||
|
vIndex = []
|
||||||
|
for f, f_index in face_index_pairs:
|
||||||
|
# confirm material use
|
||||||
|
if noMaterial:
|
||||||
|
usedMat = 0
|
||||||
|
else:
|
||||||
|
usedMat = materialList.index(currentMat[f.material_index])
|
||||||
|
|
||||||
|
# export face
|
||||||
|
vtIndex.clear()
|
||||||
|
vnIndex.clear()
|
||||||
|
vIndex.clear()
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
|
||||||
|
vIndex.append(mesh.loops[loop_index].vertex_index)
|
||||||
|
vnIndex.append(f_index * 3 + counter)
|
||||||
|
vtIndex.append(f_index * 3 + counter)
|
||||||
|
counter += 1
|
||||||
|
# reverse vertices sort
|
||||||
|
write_face(fmesh,
|
||||||
|
vIndex[2], vtIndex[2], vnIndex[2],
|
||||||
|
vIndex[1], vtIndex[1], vnIndex[1],
|
||||||
|
vIndex[0], vtIndex[0], vnIndex[0])
|
||||||
|
|
||||||
|
# set used material
|
||||||
|
write_bool(fmesh, not noMaterial)
|
||||||
|
write_uint32(fmesh, usedMat)
|
||||||
|
|
||||||
|
mesh.free_normals_split()
|
||||||
|
|
||||||
|
# ====================== export material
|
||||||
|
textureSet = set()
|
||||||
|
textureList = []
|
||||||
|
textureCount = 0
|
||||||
|
with open(os.path.join(tempFolder, "material.bm"), "wb") as fmaterial:
|
||||||
|
for material in materialList:
|
||||||
|
# write finfo first
|
||||||
|
write_string(finfo, material.name)
|
||||||
|
write_uint8(finfo, info_bm_type.MATERIAL)
|
||||||
|
write_uint64(finfo, fmaterial.tell())
|
||||||
|
|
||||||
|
# try get original written data
|
||||||
|
material_colAmbient = try_get_custom_property(material, 'virtools-ambient')
|
||||||
|
material_colDiffuse = try_get_custom_property(material, 'virtools-diffuse')
|
||||||
|
material_colSpecular = try_get_custom_property(material, 'virtools-specular')
|
||||||
|
material_colEmissive = try_get_custom_property(material, 'virtools-emissive')
|
||||||
|
material_specularPower = try_get_custom_property(material, 'virtools-power')
|
||||||
|
|
||||||
|
# get basic color
|
||||||
|
mat_wrap = node_shader_utils.PrincipledBSDFWrapper(material)
|
||||||
|
if mat_wrap:
|
||||||
|
use_mirror = mat_wrap.metallic != 0.0
|
||||||
|
if use_mirror:
|
||||||
|
material_colAmbient = set_value_when_none(material_colAmbient, (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
|
||||||
|
else:
|
||||||
|
material_colAmbient = set_value_when_none(material_colAmbient, (1.0, 1.0, 1.0))
|
||||||
|
material_colDiffuse = set_value_when_none(material_colDiffuse, (mat_wrap.base_color[0], mat_wrap.base_color[1], mat_wrap.base_color[2]))
|
||||||
|
material_colSpecular = set_value_when_none(material_colSpecular, (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular))
|
||||||
|
material_colEmissive = set_value_when_none(material_colEmissive, mat_wrap.emission_color[:3])
|
||||||
|
material_specularPower = set_value_when_none(material_specularPower, 0.0)
|
||||||
|
|
||||||
|
# confirm texture
|
||||||
|
tex_wrap = getattr(mat_wrap, "base_color_texture", None)
|
||||||
|
if tex_wrap:
|
||||||
|
image = tex_wrap.image
|
||||||
|
if image:
|
||||||
|
# add into texture list
|
||||||
|
if image not in textureSet:
|
||||||
|
textureSet.add(image)
|
||||||
|
textureList.append(image)
|
||||||
|
currentTexture = textureCount
|
||||||
|
textureCount += 1
|
||||||
|
else:
|
||||||
|
currentTexture = textureList.index(image)
|
||||||
|
|
||||||
|
material_useTexture = True
|
||||||
|
material_texture = currentTexture
|
||||||
|
else:
|
||||||
|
# no texture
|
||||||
|
material_useTexture = False
|
||||||
|
material_texture = 0
|
||||||
|
else:
|
||||||
|
# no texture
|
||||||
|
material_useTexture = False
|
||||||
|
material_texture = 0
|
||||||
|
|
||||||
|
else:
|
||||||
|
# no Principled BSDF. write garbage
|
||||||
|
material_colAmbient = set_value_when_none(material_colAmbient, (0.8, 0.8, 0.8))
|
||||||
|
material_colDiffuse = set_value_when_none(material_colDiffuse, (0.8, 0.8, 0.8))
|
||||||
|
material_colSpecular = set_value_when_none(material_colSpecular, (0.8, 0.8, 0.8))
|
||||||
|
material_colEmissive = set_value_when_none(material_colEmissive, (0.8, 0.8, 0.8))
|
||||||
|
material_specularPower = set_value_when_none(material_specularPower, 0.0)
|
||||||
|
|
||||||
material_useTexture = False
|
material_useTexture = False
|
||||||
material_texture = 0
|
material_texture = 0
|
||||||
else:
|
|
||||||
# no texture
|
|
||||||
material_useTexture = False
|
|
||||||
material_texture = 0
|
|
||||||
|
|
||||||
else:
|
write_color(fmaterial, material_colAmbient)
|
||||||
# no Principled BSDF. write garbage
|
write_color(fmaterial, material_colDiffuse)
|
||||||
material_colAmbient = set_value_when_none(material_colAmbient, (0.8, 0.8, 0.8))
|
write_color(fmaterial, material_colSpecular)
|
||||||
material_colDiffuse = set_value_when_none(material_colDiffuse, (0.8, 0.8, 0.8))
|
write_color(fmaterial, material_colEmissive)
|
||||||
material_colSpecular = set_value_when_none(material_colSpecular, (0.8, 0.8, 0.8))
|
write_float(fmaterial, material_specularPower)
|
||||||
material_colEmissive = set_value_when_none(material_colEmissive, (0.8, 0.8, 0.8))
|
write_bool(fmaterial, material_useTexture)
|
||||||
material_specularPower = set_value_when_none(material_specularPower, 0.0)
|
write_uint32(fmaterial, material_texture)
|
||||||
|
|
||||||
material_useTexture = False
|
|
||||||
material_texture = 0
|
|
||||||
|
|
||||||
write_color(fmaterial, material_colAmbient)
|
# ====================== export texture
|
||||||
write_color(fmaterial, material_colDiffuse)
|
source_dir = os.path.dirname(bpy.data.filepath)
|
||||||
write_color(fmaterial, material_colSpecular)
|
existed_texture = set()
|
||||||
write_color(fmaterial, material_colEmissive)
|
with open(os.path.join(tempFolder, "texture.bm"), "wb") as ftexture:
|
||||||
write_float(fmaterial, material_specularPower)
|
for texture in textureList:
|
||||||
write_bool(fmaterial, material_useTexture)
|
# write finfo first
|
||||||
write_uint32(fmaterial, material_texture)
|
write_string(finfo, texture.name)
|
||||||
|
write_uint8(finfo, info_bm_type.TEXTURE)
|
||||||
|
write_uint64(finfo, ftexture.tell())
|
||||||
|
|
||||||
fmaterial.close()
|
# confirm internal
|
||||||
|
texture_filepath = io_utils.path_reference(texture.filepath, source_dir, tempTextureFolder,
|
||||||
|
'ABSOLUTE', "", None, texture.library)
|
||||||
|
filename = os.path.basename(texture_filepath)
|
||||||
|
write_string(ftexture, filename)
|
||||||
|
if (is_external_texture(filename)):
|
||||||
|
write_bool(ftexture, True)
|
||||||
|
else:
|
||||||
|
# copy internal texture, if this file is copied, do not copy it again
|
||||||
|
write_bool(ftexture, False)
|
||||||
|
if filename not in existed_texture:
|
||||||
|
shutil.copy(texture_filepath, os.path.join(tempTextureFolder, filename))
|
||||||
|
existed_texture.add(filename)
|
||||||
|
|
||||||
# ====================== export texture
|
|
||||||
ftexture = open(os.path.join(tempFolder, "texture.bm"), "wb")
|
|
||||||
source_dir = os.path.dirname(bpy.data.filepath)
|
|
||||||
existed_texture = set()
|
|
||||||
|
|
||||||
for texture in textureList:
|
|
||||||
# write finfo first
|
|
||||||
write_string(finfo, texture.name)
|
|
||||||
write_uint8(finfo, info_bm_type.TEXTURE)
|
|
||||||
write_uint64(finfo, ftexture.tell())
|
|
||||||
|
|
||||||
# confirm internal
|
|
||||||
texture_filepath = io_utils.path_reference(texture.filepath, source_dir, tempTextureFolder,
|
|
||||||
'ABSOLUTE', "", None, texture.library)
|
|
||||||
filename = os.path.basename(texture_filepath)
|
|
||||||
write_string(ftexture, filename)
|
|
||||||
if (is_external_texture(filename)):
|
|
||||||
write_bool(ftexture, True)
|
|
||||||
else:
|
|
||||||
# copy internal texture, if this file is copied, do not copy it again
|
|
||||||
write_bool(ftexture, False)
|
|
||||||
if filename not in existed_texture:
|
|
||||||
shutil.copy(texture_filepath, os.path.join(tempTextureFolder, filename))
|
|
||||||
existed_texture.add(filename)
|
|
||||||
|
|
||||||
ftexture.close()
|
|
||||||
|
|
||||||
# close info fs
|
|
||||||
finfo.close()
|
|
||||||
|
|
||||||
# ============================================ save zip and clean up folder
|
# ============================================ save zip and clean up folder
|
||||||
if os.path.isfile(filepath):
|
if os.path.isfile(filepath):
|
||||||
|
Loading…
Reference in New Issue
Block a user