# How could one unwrap/morph/project a complex 3D mesh to a flat surface?

I'm working with a 3D mesh (non-convex) and would like to achieve a similar effect as shown in the following video:

In other words, if I'm starting with a mesh that looks like this:

I would like to flatten/unwrap/morph/project its vertices to a flat plane mesh like this:

I'm looking for a general process of how this could be done. An example, e.g with Suzanne, would be helpful.

I recognize that this is somewhat similar to UV-unwrapping. However, it's not clear to me how one would go about creating flat 3D mesh vertices from the UV map data.

This could also be done by moving each mesh vertex to the desired position on a plane, but I wonder if there is a more efficient method.

• I think this is the answer you are looking for: blender.stackexchange.com/questions/40157/… – cgslav Aug 26 at 20:24
• @cgslav Thank you for the link. That looks very close to what I'm looking for. I will give it a try – Justas Aug 26 at 20:51

The script should be run in object mode.

The script will report UV map coordinates into a shape key, so that you can animate the shape key.

You need to prepare the mesh: mark seams and make your UV map (you may need to move rotate, scale the uv isles as you wish). If you modify the UV map, run the script again so that the shape key will be updated.

The seams are important because the script will use them to split the original mesh (so your mesh will be modified by the script).

These splits are done because we want each vertex to have only one correspondent uv vertex in the uv map.

It is commented, below, but if some more details are needed, please ask:

import bpy
import bmesh
from mathutils import Vector

print( "------------" )

shape_key_name = "test"
object_name = "Suzanne"
uv_map_name = "UVMap"

obj = bpy.data.objects[object_name]

# Prepare the shape keys

if not obj.data.shape_keys:

shape_key = obj.data.shape_keys.key_blocks.get( shape_key_name )

if shape_key:
obj.shape_key_remove( shape_key )

shape_key = obj.shape_key_add( name = shape_key_name )

# Cut the mesh

# Get a bmesh from the object mesh
bm = bmesh.new()
bm.from_mesh( obj.data )

# Prepare the mesh
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()

# Split edges that have seam and link to 2 faces
edges = [e for e in bm.edges if e.seam and len(e.link_faces) == 2]
bmesh.ops.split_edges( bm, edges = edges )

# Give the new geometry back to the object
bm.to_mesh( obj.data )

# Get the uv map
uv_map = obj.data.uv_layers[uv_map_name]

# Assign the coordinates to the shape key
for loop, uv_data in zip( obj.data.loops, uv_map.data ):
uv = uv_data.uv
vertex_index = loop.vertex_index
shape_key.data[vertex_index].co = Vector( (uv.x, 0, uv.y) )


• Wow. This is really cool. You basically made a UV map -> 2D mesh converter – Justas Aug 27 at 19:24
• @Justas FYI there is an API to convert a UV map to mesh. But we can't use it here as we need vertex order coherency for shape keys. – lemon Aug 28 at 5:25