Hy All

Im a blender noob trying to get a font texturised in blender. Thats how i plan to do it:

  • create the font (is a curve)
  • convert the curve to mesh
  • uv_unwrap the mesh from view (i need just plain unwrapping, since its 2d)
  • add material
  • render

So far all works except the unwrap which leaves me with a horridly distorted mapping of the image.

myFontCurve = bpy.data.curves.new(type="FONT",name="font")
myFontOb = bpy.data.objects.new("myFontOb",myFontCurve)
myFontOb.data.body = "my text"
# Set Material
mat = bpy.data.materials['Material'] #Material Nodes Settings are done in gui
# We use nodes here... 
mat.use_nodes = True
backgroundfile = "pathtoaffile.jpg"
mat.node_tree.nodes["ColorTexture"].image = bpy.data.images.load(backgroundfile)
# Assign Material to Object                                           
if myFontOb.data.materials:
    myFontOb.data.materials[0] = mat
bpy.data.objects["myFontOb"].uv.project_from_view(orthographic=False, correct_aspect=True, clip_to_bounds=False, scale_to_bounds=False)
# Render the letter
output = "path to file.jpg"
bpy.context.scene.render.filepath = output
bpy.ops.render.render(write_still = True) 

My attempt to do so with unwrap_from_view fail with "'Object' object has no attribute 'uv'".

Like i said, im a rookie and help would be very much appreciated.

If somebody could point me in the right direction, that would be awesome.

Thanks you


1 Answer 1


Use the mesh coords

The issue with your script is you are mixing objects and operators.

Here is the autocomplete of the project from view operator in the console.

>>> bpy.ops.uv.project_from_view(
bpy.ops.uv.project_from_view(orthographic=False, camera_bounds=True, correct_aspect=True, clip_to_bounds=False, scale_to_bounds=False)
Project the UV vertices of the mesh as seen in current 3D view

Trying with C.object.uv. will throw same error as in question since an object has no property uv.

At issue with operators that use the view is they are designed to be run from within that view (it has context) via a button or menu item. Using in script will often require passing an override context or other dicking around, however for this would simply write the UV directly from the mesh coordinates.

To convert the context object to a mesh

>>> bpy.ops.object.convert(
bpy.ops.object.convert(target='MESH', keep_original=False, angle=1.22173, thickness=5, seams=False, faces=True, offset=0.01)
Convert selected objects to another type

So with a curve object as context object

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

eg this can be called directly after adding the font object and setting its body text.

Using the mesh coordinates

The UV operator template in Text Editor > Templates > Python > Operator UV adds a UV that is pretty much an orthogonal projection from above as it uses the x and y vertex coordinate as UV.

Here I've tweaked it to normalize the U and V to 0, 1 range. To have same aspect would scale by the minimum of the X and Y range.

enter image description here

import bpy
import bmesh
import numpy as np
from mathutils import Matrix

def main(obj):
    me = obj.data
    bm = bmesh.new()
    #bm = bmesh.from_edit_mesh(me)
    x, y, z = np.array([v.co for v in bm.verts]).T
    S = Matrix.Diagonal(
        ( 1 / (x.max() - x.min()),
          1 / (y.max() - y.min()))
    uv_layer = bm.loops.layers.uv.verify()
    # adjust uv coordinates
    for face in bm.faces:
        for loop in face.loops:
            loop_uv = loop[uv_layer]
            # use xy position of the vertex as a uv coordinate
            loop_uv.uv = S @ loop.vert.co.xy


# Test call    
  • $\begingroup$ Thanks a lot! You are legend... made it work after fiddling around with it too long. If you make your way to Da Nang, Vietnam, let me know. you should try the egg coffee here :) $\endgroup$
    – philzphil
    Jul 7, 2020 at 18:25

You must log in to answer this question.

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