As far as I know there's no way to duplicate an object copying only its mesh data using built-in commands. There are probably add-ons that do this as one of their functions, but I couldn't find one so I wrote this:
import bpy
from bpy.types import Operator
bl_info = {
"name" : "Simple Duplicator",
"description" : "Duplicate an object, copying only the mesh",
"author" : "Marty Fouts <fouts@fogey.com>",
"version" : (0, 0, 1),
"blender" : (2, 83, 0),
"location" : "View3D",
"warning" : "",
"support" : "COMMUNITY",
"doc_url" : "",
"category" : "Object"
}
def object_mesh_duplicate_draw(self, context):
"""Menu entry for mesh Duplicator"""
self.layout.separator()
self.layout.operator("mop.mesh_duplicate",
icon="OUTLINER_DATA_MESH")
This function was provided by Blender StackExchange User scurest
I've modified it to work in the context of the existing code.
def do_copy_pure_geometry(src_mesh):
dst_mesh = bpy.data.meshes.new(name=src_mesh.name)
def copy_over(attr_name, sub_name, components=1):
src_attr = getattr(src_mesh, attr_name)
dst_attr = getattr(dst_mesh, attr_name)
if len(dst_attr) != len(src_attr):
dst_attr.add(len(src_attr))
arr = [None] * (len(dst_attr) * components)
src_attr.foreach_get(sub_name, arr)
dst_attr.foreach_set(sub_name, arr)
copy_over("vertices", "co", components=3)
copy_over("edges", "vertices", components=2)
copy_over("loops", "vertex_index")
copy_over("polygons", "loop_start")
copy_over("polygons", "loop_total")
dst_mesh.validate()
dst_mesh.update(calc_edges_loose=True)
return dst_mesh
class MOP_OT_mesh_duplicate(Operator):
"""Copy only the mesh of an object when duplicating it"""
bl_idname = "mop.mesh_duplicate"
bl_label = "duplicate mesh"
bl_description = "Duplicate only the mesh of an object"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.mode == 'OBJECT' \
and context.object \
and context.object.type == 'MESH'
def execute(self, context):
object = context.object
new_mesh = do_copy_pure_geometry(object.data)
new_object = bpy.data.objects.new(object.name, new_mesh)
context.collection.objects.link(new_object)
new_object.select_set(True)
object.select_set(False)
context.view_layer.objects.active = new_object
return {'FINISHED'}
def register():
bpy.utils.register_class(MOP_OT_mesh_duplicate)
bpy.types.VIEW3D_MT_object.append(object_mesh_duplicate_draw)
def unregister():
bpy.utils.unregister_class(MOP_OT_mesh_duplicate)
bpy.types.VIEW3D_MT_object.remove(object_mesh_duplicate_draw)
if name == "main":
register()
You can copy it into the text editor in Blender and run it, or you can install it as an add-on and enable it. Either way it adds an entry to the bottom of the 3D Viewport's Object menu called duplicate mesh that will duplicate the active object but only its mesh into a new object. You can also invoke it by using F3 and search for 'duplicate'. I didn't add a shortcut for it, because whatever I pick will probably be something you're already using.
Here's a test file with a non-mesh object and a mesh-object that has various additions to the mesh, including modifiers, marked edges, and vertex colors:

vertices.co,edges.vertices,loops.vertex_index,polygons.loop_start, andpolygons.loop_total. Example – scurest Nov 06 '21 at 19:00