3
$\begingroup$

enter image description here

I have a setup, a very complex instancing, I simply want to Voxel Remesh this (sculpt) but if I use Make Real for instances, it will create bazillions instances, and I don't want that. I simply need a joined mesh based on the parented dupli instances, regardles how complex, and from that single mesh, then I can use Voxel Remesh or other processing.

Any idea?

$\endgroup$
3
$\begingroup$

Make real and join*

Could make the mesh by making the dupliobject active and running make duplicates real, and then joining them. Sorry haven't fixed the location properly

import bpy

context = bpy.context
scene = context.scene
vl = context.view_layer

obs = set(scene.objects)
bpy.ops.object.duplicates_make_real()
new_obs = list(set(scene.objects) - obs)
bpy.ops.object.select_all(action='DESELECT')
o = new_obs[0]
vl.objects.active = o
for o in new_obs:
    o.select_set(True)

bpy.ops.object.join()

Using depsgraph in 2.8

enter image description here Result in edit mode above, default torus duplivert default and scaled down icosphere. May be cuppa time while it runs

Instances can be obtained from the depsgraph. https://docs.blender.org/api/master/bpy.types.DepsgraphObjectInstance.html#module-bpy.types

There is a section in

https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/Scene_and_Object_API

re getting the instances of an object via the python API.

Using the method prescribed for getting instances of a particular object, here is a test script to create a bmesh from all object instances of the context object,

The bmesh is written to new single mesh object from the instances. The mesh equivalent of make real and join. (Without the original)

I have only tested this on a very simple example, without materials.

import bpy
import bmesh

context = bpy.context
ob = context.object
mwi = ob.matrix_world.inverted()
dg = context.evaluated_depsgraph_get()

bm = bmesh.new()
for ob_inst in dg.object_instances:
    if ob_inst.parent and ob_inst.parent.original == ob:
        me = ob_inst.instance_object.data
        bm.from_mesh(me)
        # transform to match instance
        bmesh.ops.transform(bm,
                matrix=mwi @ ob_inst.matrix_world,
                verts=bm.verts[-len(me.vertices):]
                )

# link an object with the instanced mesh

me = bpy.data.meshes.new(f"{ob.data.name}_InstanceMesh")
bm.to_mesh(me)
ob_ev = bpy.data.objects.new(f"{ob.name}_InstancedObject", me) 
ob_ev.matrix_world = ob.matrix_world

context.collection.objects.link(ob_ev)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Interesting, appreciate the post. Works like a charm but still takes a few seconds for ~500 spheres on my machine though. $\endgroup$ – p2or Aug 21 '19 at 11:26
  • 1
    $\begingroup$ Thankyou. Could try without the bmesh by generating using from_pydata, with some numpy trickery Hence prob not most efficient, Added the operator approach with make real then join. $\endgroup$ – batFINGER Aug 21 '19 at 12:22
  • $\begingroup$ Thanks so much!!! This works well and faster than "making copy real" and joining it back. $\endgroup$ – Blender Sushi Guy Aug 22 '19 at 1:19
0
$\begingroup$

I just discovered that

bpy.ops.object.convert(target='MESH')

will apply the visual mesh and remove all the modifiers, linked or not. handy for cleaning up linked modifiers after making all instances real.

you can find it on ctrl+a as "apply visual mesh"

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.