0

I wrote a script to join mesh using bmesh module but the meshes are joining in one location.

import bpy, bmesh

bm = bmesh.new()

for object in bpy.context.selected_objects: bm.from_mesh(object.data)

mesh = bpy.data.meshes.new('Test') bm.to_mesh(mesh) mesh.update() bm.free()

obj = bpy.data.objects.new('Test', mesh) bpy.context.collection.objects.link(obj)

enter image description here

The selected object is the new object with joined meshes but all the meshes are in one location.

Karan
  • 1,984
  • 5
  • 21

2 Answers2

1

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)

Psyonic
  • 2,319
  • 8
  • 13
1

You can transform the mesh into world space before you add it to the BMesh. Because you probably don't want to modify the original mesh, you can create a temp copy of the mesh and transform that instead.

import bpy, bmesh

def add_mesh_to_bmesh(bm, mesh, matrix): """bm.from_mesh(mesh), but it applies matrix to mesh first""" tmp_mesh = None try: tmp_mesh = mesh.copy() tmp_mesh.transform(matrix) bm.from_mesh(tmp_mesh) finally: if tmp_mesh: bpy.data.meshes.remove(tmp_mesh)

bm = bmesh.new()

for object in bpy.context.selected_objects: add_mesh_to_bmesh(bm, object.data, object.matrix_world)

mesh = bpy.data.meshes.new('Test') bm.to_mesh(mesh) mesh.update() bm.free()

obj = bpy.data.objects.new('Test', mesh) bpy.context.collection.objects.link(obj)

scurest
  • 10,349
  • 13
  • 31