0
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ Have you tried this ? blender.stackexchange.com/a/50186/53447 $\endgroup$
    – L0Lock
    Mar 24 at 21:09
  • $\begingroup$ Yes, bm.from_mesh(object.data) $\endgroup$
    – Karan
    Mar 24 at 21:11
  • $\begingroup$ Oh yeah sorry i misread your code x) $\endgroup$
    – L0Lock
    Mar 24 at 23:00

2 Answers 2

0
$\begingroup$

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)
$\endgroup$
1
  • $\begingroup$ can you extend it for edit mode mesh? $\endgroup$
    – Karan
    Mar 26 at 5:32
0
$\begingroup$

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)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .