6
$\begingroup$

So what I've been doing to bake Cycles depth maps is based on the following thread found on the BA.org forum and I've mentioned this here already but I'd like to take this a step further using a script but I'm not sure how to do this myself.

If you have a look at the following thread, there is a method for creating Cycles Depth maps using an Orthographic camera but it's limited to planer objects.

http://blenderartists.org/forum/showthread.php?273033-Sculpting-with-UVs-and-displacements/page34

I've expanded this technique slightly by baking an objects' color as white and with no Margin overdraw so that I have a guide for using the above mentioned technique but in a more 3D way since the resulting texture will match up with the 3D Objects UV coordinates.

Basically, this is how I modeled the pillars on the following model.

enter image description here

and the setup looks like this.

enter image description here

The problem is that we have to be very careful around the UV Island boundaries because if the depth map does not match up perfectly with the UV's then the Displace modifier will make a big mess at all the seams.

So this brings me to the question. How can we convert a UV coordinate set into an actual flat 3D mesh that would still match up perfectly with the UV's of the model they were created from. Here is an image to help illustrate this. enter image description here

So does anyone have some thoughts on how to make a script that can make this conversion from UV's to a new mesh that looks exactly like the UV's of the first model so that the Cycles Camera Depth map technique can be used to make perfectly aligned displacement UV maps?

X and Y should translate directly into the new meshs' X and Y positions and z would be set to be all 0's. This worked when I did it with GLSL so it should work here as well.

So I guess my question is how can we write a script using Blender Python that does this?

$\endgroup$
12
$\begingroup$

In Object Mode with an object selected (tested with an unwrapped cube)

import bpy

ob = bpy.context.object

def createMeshFromData(name, verts, faces):
    # Create mesh and object
    me = bpy.data.meshes.new(name+'Mesh')
    ob = bpy.data.objects.new(name, me)
    ob.show_name = True

    # Link object to scene and make active
    scn = bpy.context.scene
    scn.objects.link(ob)
    scn.objects.active = ob
    ob.select = True

    # Create mesh from given verts, faces.
    me.from_pydata(verts, [], faces)
    # Update mesh with new data
    me.update()    
    return ob

out_verts=[]
out_faces=[]
for face in ob.data.polygons:
    oface=[]   
    for vert, loop in zip(face.vertices, face.loop_indices):
        coord = ob.data.vertices[vert].normal
        normal = ob.data.vertices[vert].co
        uv = ob.data.uv_layers.active.data[loop].uv 
        out_verts.append((uv.x*10,uv.y*10,0))
        oface.append(loop)
    print(oface)
    out_faces.append(oface)

createMeshFromData(ob.name + 'UVObj', out_verts, out_faces)

If you are using Blender 2.8 series, the script below does the exact same thing. Note that there is a size variable introduced to help scale the output mesh if needed:

import bpy

C = bpy.context
ob = C.object
size = 10.0

def createMeshFromData(name, verts, faces):
    # Create mesh and object
    me = bpy.data.meshes.new(name+'Mesh')
    ob = bpy.data.objects.new(name, me)
    ob.show_name = True

    # Link object to scene and make active
    C.view_layer.active_layer_collection.collection.objects.link(ob)
    C.view_layer.objects.active = ob
    ob.select_set(True)

    # Create mesh from given verts, faces.
    me.from_pydata(verts, [], faces)
    # Update mesh with new data
    me.update()    
    return ob

out_verts=[]
out_faces=[]
for face in ob.data.polygons:
    oface=[]   
    for vert, loop in zip(face.vertices, face.loop_indices):
        coord = ob.data.vertices[vert].normal
        normal = ob.data.vertices[vert].co
        uv = ob.data.uv_layers.active.data[loop].uv 
        out_verts.append((uv.x*size,uv.y*size,0))
        oface.append(loop)
    print(oface)
    out_faces.append(oface)

createMeshFromData(ob.name + 'UVObj', out_verts, out_faces)

Result:

enter image description here

$\endgroup$
  • $\begingroup$ I changed the following line and now it aligns perfectly with a UV baked texture that is loaded in using the Images As Planes Addon -> out_verts.append((uv.x-0.5,uv.y-0.5,0)) You're a champ, this is awesome. $\endgroup$ – MarcClintDion Jul 15 '14 at 20:01
  • $\begingroup$ I found the script very usefull, but it doesn't give me a correctly scaled mesh. I got a tiny tiny mesh instead, is there a scale factor to be applied? $\endgroup$ – piepolitb Oct 14 '14 at 14:24
  • 1
    $\begingroup$ @piepolitb you could try to increase the factor 10 in this line out_verts.append((uv.x*10,uv.y*10,0)) $\endgroup$ – stacker Oct 14 '14 at 15:34
  • $\begingroup$ Awesome script. @piepolitb Set your units to None and it outputs the correct scale. Mine was set to Meters and I had the same scaling issue. $\endgroup$ – Gavh Jul 24 at 8:14

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.