bmesh
will always put new data at world 0,0,0
You need to copy the location, rotation and scale data from the original to preserve those attributes:
(I learnt why this is a long time ago but have now forgotten 😜 All I know is it works)
import bpy, bmesh
from mathutils import Matrix
final_bm = bmesh.new()
for object in bpy.context.selected_objects:
# create temp bmesh of selected objects 1 by 1
bm_tmp = bmesh.new()
bm_tmp.from_mesh(object.data)
tmp_mesh = bpy.data.meshes.new("temp_mesh")
bm_tmp.to_mesh(tmp_mesh)
bm_tmp.free()
tmp_obj = bpy.data.objects.new("tmp_obj", tmp_mesh)
# retain location, rotation and scale of original object
mx = object.matrix_world
location, rotation, scale = mx.decompose()
scale_mx = Matrix()
for i in range(3):
scale_mx[i][i] = scale[i]
applymx = Matrix.Translation(location) @ rotation.to_matrix().to_4x4() @ scale_mx
tmp_obj.data.transform(applymx)
# add object to final bmesh and clean up
final_bm.from_mesh(tmp_obj.data)
old_mesh = tmp_obj.data
bpy.data.objects.remove(tmp_obj)
bpy.data.meshes.remove(old_mesh)
# create final mesh and object
mesh = bpy.data.meshes.new('Final Mesh')
final_bm.to_mesh(mesh)
mesh.update()
final_bm.free()
obj = bpy.data.objects.new('Final Object', mesh)
bpy.context.collection.objects.link(obj)
bm.from_mesh(object.data)
$\endgroup$