Wednesday, March 21, 2012

Blender to Three.js >> Create 3D Text With Any Font


Screen capture of 3D text in Three.js

Thanks to Zz85's work, Three ,js has excellent 3D text creation capabilities. These are described in the Three.js wiki and in a post on Zz85's website. If there is an issue it is that the 3D text uses fonts that have been converted into a special format developed by Typeface.js (as of this writing the web site is not operational) - and is described here.

There can be times, however, when you need to use a specific TTF font and want to be able to do so fairly quickly and easily. Or it may be that you might need custom kerning of text or text with a taper. Again this post if for you.

The technique described here uses a Python script to generate text inside Blender, export the text in JSON format using the Three.js blender export script and then load the text into a Three.js applet. Loading a Python script into Blender is described here.

Below is the Python script I used to generate three lines of text with each line using a different font all as shown in my3D text demo. Each line of extruded text uses a different material and the text is beveled.



import bpy
import math
from math import pi
# delete any meshes or text in the current drawing
def removeObjects( scn ):
    for ob in scn.objects:
        if ob.type == 'FONT' or ob.type == 'MESH':
            scn.objects.unlink( ob )    
scn = bpy.context.scene
removeObjects( scn )

# create several materials - each text line will use a different material
def  makeMaterial(name,  diffuse,  specular,  alpha):
    mat  =  bpy.data.materials.new(name)
    mat.diffuse_color  =  diffuse
    mat.diffuse_shader = 'LAMBERT'
    mat.diffuse_intensity  =  1.0
    mat.specular_color  =  specular
    mat.specular_shader  = 'COOKTORR'
    mat.specular_intensity  =  0.5
    mat.alpha  =  alpha
    mat.ambient  =  1
    return  mat

def  setMaterial(ob,  mat):
    me  =  ob.data
    me.materials.append(mat)
    
red  =  makeMaterial('Red', (1, 0, 0),  (1, 1, 1),  1)
blue  =  makeMaterial('BlueSemi', (0, 0, 1), (1, 1, 1), 0.5)
green  =  makeMaterial('GreenSemi', (0, 1, 0), (1, 1, 1), 0.5)
yellow  =  makeMaterial('YellowSemi', (1, 1, 0), (1, 1, 1), 0.5)

# Create and name TextCurve object #1
bpy.ops.object.text_add(
location=(-3, 0, 3.6),
rotation=(pi/2, 0, 0))
ob = bpy.context.object
ob.name = 'Text1'
# TextCurve attributes
ob.data.name = 'TextData1'
ob.data.body = "THREE.JS"
fnt = bpy.data.fonts.load('C:\\Windows\\Fonts\\Impact.ttf')
ob.data.font = fnt
ob.data.size = 2.75
# Inherited Curve attributes
ob.data.bevel_depth = 0.1
ob.data.bevel_resolution = 5
ob.data.extrude = 0.5
setMaterial(ob, red)
bpy.ops.object.convert(target='MESH', keep_original=False)

# Create and name TextCurve object #2
bpy.ops.object.text_add(
location=(-3, 0, 1.6),
rotation=(pi/2, 0, 0))
ob = bpy.context.object
ob.name = 'Text2'
# TextCurve attributes
ob.data.name = 'TextData2'
ob.data.body = "TEXT"
fnt = bpy.data.fonts.load('C:\\Windows\\Fonts\\Georgia.ttf')
ob.data.font = fnt
ob.data.bevel_depth = 0.1
ob.data.bevel_resolution = 5
ob.data.size = 3
# Inherited Curve attributes
ob.data.extrude = 0.5
setMaterial(ob, green)
bpy.ops.object.convert(target='MESH', keep_original=False)

# Create and name TextCurve object #3
bpy.ops.object.text_add(
location=(-3, 0, 0),
rotation=(1.51, 0, 0))
ob = bpy.context.object
ob.name = 'Text3'
# TextCurve attributes
ob.data.body = "DEMO"
ob.data.name = 'TextData3'
fnt = bpy.data.fonts.load('C:\\Windows\\Fonts\\coopbl.ttf')
ob.data.font = fnt
ob.data.bevel_depth = 0.1
ob.data.bevel_resolution = 5
ob.data.size = 2.32
# Inherited Curve attributes
ob.data.extrude = 0.5
setMaterial(ob, yellow)
bpy.ops.object.convert(target='MESH', keep_original=False)

// convert text to meshes so they can be exported 
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.uv.smart_project()
bpy.ops.object.mode_set(mode='OBJECT')

Why do I do it this way? I happen to find it much easier to program in Python than to learn the Blender user interface. ;-)

Please note that I did nothing to reduce file sizes so the JSON files amount to over 10MB - so it could take a file to load the demo the first time - or you might have to reload. Also you can use mouse button down to rotate/zoom/pan the view.

Link to demo
http://theo-armour.github.com/threo.js/anims/text/index.html
Source code
https://github.com/theo-armour/threo.js/tree/gh-pages/anims/text