def project_decal_old(mesh_src, mesh_dst): if isinstance(mesh_src, str): mesh_src = bpy.data.meshes.get(mesh_src) print (mesh_src) if isinstance(mesh_dst, str): mesh_dst = bpy.data.meshes.get(mesh_dst) print (mesh_dst) if mesh_src is None or mesh_dst is None: print ("src or dst is None") return bm_src = bmesh.new() bm_src.from_mesh(mesh_src) bm_dst = bmesh.new() bm_dst.from_mesh(mesh_dst) bm_out = bmesh.new() for face_src in bm_src.faces: verts_src = [] for loop_src in face_src.loops: verts_src.append(loop_src.vert.co) for face_dst in bm_dst.faces: verts_dst = [] for loop_dst in face_dst.loops: verts_dst.append(loop_dst.vert.co) # 目前做了这个假设,所以先测试到这一步 if len(verts_src) != 4 or len(verts_dst) != 3: continue # adapt arguments && run rect = [] for co in verts_src: rect.append((co.x, co.y, co.z)) tri = [] for co in verts_dst: tri.append((co.x, co.y, co.z)) res = decal_algo.decal(rect, tri) # add verts for x, y, z in res: bm_out.verts.new((x, y, z + 0.01)) # add face (all these verts will be on the same plane, so let's blender do triangulate for us) if res: bm_out.faces.new(bm_out.verts[-len(res):]) print(len(bm_out.verts)) if len(bm_out.verts) >= 0: mesh = bpy.data.meshes.new(name="_decal") bm_out.to_mesh(mesh) obj = bpy.context.scene.objects.get("_decal") if obj is None: obj = bpy.data.objects.new("_decal", mesh) bpy.context.scene.objects.link(obj) else: obj.data = mesh
def project_model(model_src, model_dst): model_src = norm_model(model_src) model_dst = norm_model(model_dst) if not (model_src and model_dst): print ("model_src or model_dst is None", model_src, model_dst) return mesh_src = model_src.data mesh_dst = model_dst.data bm_src = bmesh.new() bm_src.from_mesh(mesh_src) bm_dst = bmesh.new() bm_dst.from_mesh(mesh_dst) bm_out = bmesh.new() # world to decal matrix if hasattr(bm_src.faces, "ensure_lookup_table"): bm_src.faces.ensure_lookup_table() o = model_src.matrix_world * bm_src.faces[0].loops[0].vert.co a = model_src.matrix_world * bm_src.faces[0].loops[-1].vert.co b = model_src.matrix_world * bm_src.faces[0].loops[1].vert.co oa = a - o axis_x = oa.normalized() ob = b - o axis_y = ob.normalized() axis_z = oa.cross(ob).normalized() # uv uv_layer = bm_src.loops.layers.uv.active uv_o = bm_src.faces[0].loops[0][uv_layer].uv uv_a = bm_src.faces[0].loops[-1][uv_layer].uv uv_b = bm_src.faces[0].loops[1][uv_layer].uv world_to_decal = mathutils.Matrix() world_to_decal[0][:] = (axis_x.x, axis_x.y, axis_x.z, 0.0) world_to_decal[1][:] = (axis_y.x, axis_y.y, axis_y.z, 0.0) world_to_decal[2][:] = (axis_z.x, axis_z.y, axis_z.z, 0.0) world_to_decal[3][:] = (0.0, 0.0, 0.0, 1.0) world_to_decal *= mathutils.Matrix.Translation(-o) # decal to world matrix decal_to_world = world_to_decal.inverted() # src to decal matrix src_to_decal = world_to_decal * model_src.matrix_world # dst to decal matrix dst_to_decal = world_to_decal * model_dst.matrix_world added_vert_count = 0 uvs = [] for face_src in bm_src.faces: verts_src = [] for loop_src in face_src.loops: verts_src.append(src_to_decal * loop_src.vert.co) for face_dst in bm_dst.faces: verts_dst = [] for loop_dst in face_dst.loops: verts_dst.append(dst_to_decal * loop_dst.vert.co) # 目前做了这个假设,所以先测试到这一步 if len(verts_src) != 4 or len(verts_dst) != 3: continue # adapt arguments && run rect = [] #print ("rect:") for co in reversed(verts_src): #print ("\t", co) rect.append((co.x, co.y, co.z)) tri = [] #print ("tri:") for co in verts_dst: #print ("\t", co) tri.append((co.x, co.y, co.z)) res = decal_algo.decal(rect, tri) # add verts for x, y, z in res: #print (x, y) import common_algo #assert common_algo.dblcmp(x) >= 0 and common_algo.dblcmp(y) >= 0, "should x, y all be positive in decal space" fx = x / oa.length u = uv_o.x * (1 - fx) + uv_a.x * fx fy = y / ob.length v = uv_o.y * (1 - fy) + uv_b.y * fy uvs.append((u, v)) print ("u, v:", u, v) vec_decal = mathutils.Vector((x, y, z)) vec_world = decal_to_world * vec_decal # should offset along which direction? vec_world.z += 0.01 bm_out.verts.new(vec_world) added_vert_count += len(res) # SB blender bm_out.verts.index_update() if hasattr(bm_out.verts, "ensure_lookup_table"): bm_out.verts.ensure_lookup_table() # add face (all these verts will be on the same plane, so let's blender do triangulate for us) if res: bm_out.faces.new(bm_out.verts[-len(res):]) # output print(len(bm_out.verts), added_vert_count) if len(bm_out.verts) >= 0: mesh = bpy.data.meshes.new(name="_decal") bm_out.to_mesh(mesh) # it seems like that bmesh can't modify uv at the moment mesh.uv_textures.new("tex_decal") for loop in mesh.loops: setattr(mesh.uv_layers[0].data[loop.index], "uv", uvs[loop.vertex_index]) print (uvs[loop.vertex_index]) for uv_face in mesh.uv_textures.active.data: uv_face.image = bpy.data.images["Checker"] obj = bpy.context.scene.objects.get("_decal") if obj is None: obj = bpy.data.objects.new("_decal", mesh) bpy.context.scene.objects.link(obj) else: obj.data = mesh