1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| import bpy import bmesh import sys import os
argv = sys.argv argv = argv[argv.index("--") + 1:]
if len(argv) < 2: print("Usage: blender --background --python convert_ply_to_obj.py -- <input_ply_file> <output_obj_file>") sys.exit(1)
input_ply_path = argv[0] output_obj_path = argv[1]
def load_ply(file_path): bpy.ops.import_mesh.ply(filepath=file_path)
def add_vertex_color_material(): obj = bpy.context.object mat = bpy.data.materials.new(name="VertexColorMaterial") mat.use_nodes = True nodes = mat.node_tree.nodes
for node in nodes: nodes.remove(node)
output_node = nodes.new(type="ShaderNodeOutputMaterial") diffuse_node = nodes.new(type="ShaderNodeBsdfDiffuse") vertex_color_node = nodes.new(type="ShaderNodeVertexColor")
output_node.location = (300, 0) diffuse_node.location = (0, 0) vertex_color_node.location = (-300, 0)
mat.node_tree.links.new(output_node.inputs['Surface'], diffuse_node.outputs['BSDF']) mat.node_tree.links.new(diffuse_node.inputs['Color'], vertex_color_node.outputs['Color'])
if obj.data.materials: obj.data.materials[0] = mat else: obj.data.materials.append(mat)
def bake_vertex_colors_to_texture(output_image_path): bpy.context.scene.render.engine = 'CYCLES' bpy.context.scene.cycles.device = 'CPU'
obj = bpy.context.object
mat = bpy.data.materials.new(name="BakedMaterial") mat.use_nodes = True nodes = mat.node_tree.nodes
for node in nodes: nodes.remove(node)
output_node = nodes.new(type="ShaderNodeOutputMaterial") emission_node = nodes.new(type="ShaderNodeEmission") vertex_color_node = nodes.new(type="ShaderNodeVertexColor")
output_node.location = (300, 0) emission_node.location = (0, 0) vertex_color_node.location = (-300, 0)
mat.node_tree.links.new(output_node.inputs['Surface'], emission_node.outputs['Emission']) mat.node_tree.links.new(emission_node.inputs['Color'], vertex_color_node.outputs['Color'])
if obj.data.materials: obj.data.materials[0] = mat else: obj.data.materials.append(mat)
image = bpy.data.images.new(name="BakedVertexColors", width=1024, height=1024) texture_node = nodes.new(type="ShaderNodeTexImage") texture_node.image = image texture_node.location = (-600, 0)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.uv.smart_project() bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.scene.render.bake.use_pass_direct = False bpy.context.scene.render.bake.use_pass_indirect = False bpy.context.scene.render.bake.use_pass_color = True bpy.context.scene.render.bake.target = 'IMAGE_TEXTURES' texture_node.select = True nodes.active = texture_node
bpy.ops.object.bake(type='EMIT')
image.filepath_raw = output_image_path image.file_format = 'PNG' image.save()
def export_obj(file_path, texture_file): bpy.ops.export_scene.obj(filepath=file_path, use_materials=True) mtl_file_path = file_path.replace('.obj', '.mtl') if os.path.exists(mtl_file_path): with open(mtl_file_path, 'a') as mtl_file: mtl_file.write(f"\nmap_Kd {texture_file}\n")
def main(input_ply_path, output_obj_path): bpy.ops.wm.read_factory_settings(use_empty=True)
load_ply(input_ply_path)
add_vertex_color_material()
output_image_path = os.path.splitext(output_obj_path)[0] + "_vertex_colors.png" bake_vertex_colors_to_texture(output_image_path)
export_obj(output_obj_path, os.path.basename(output_image_path))
main(input_ply_path, output_obj_path)
|