z3r0_d, thanks for the Vcol Paint tip… you just saved me about one extra hour of frustration.
About the Texture baking scrip… I decided not to give up with it, and I finally understud what was going wrong:
Things to have in mind when using JMS’s Texture Baking Script
-
It creates 3 objects: a flattened mesh, a cammera and a lamp.
-
all the 3 objects are placed on layer 1, if that layer is not visible while you use the script all you will get a is an empty render.
-
The flattened mesh is really flattend only after frame 100 (if you playback the animation, you can actually see the mesh becoming flat on the first 100 frames).
-
When the script is run, it changes temporary to the new cammera, set the render output to a square (i.e. 1024 x 1024), does the render, and then reset the render output and the active camera to the original ones.
-
Everytime you run the script a new set of objects is created. File size and memory consumption can go pretty high if you are not aware of that (by the time I realised the file was already 59 MB in size and the computer was freezing because "not-enough-memory errors).
*Since the 3 objects are left there after the script runs, if you manually reasing the new camera as the active one and set your render-output settings yourself you can override the rendersize limitations of the script. 
Something that I really liked about z3r0_d’s script is that it tells you all those things beforehand, so you are not navigating blindlfolded on the sea. Z3r0_d’s script doesn’t have exactly the same peculiarities as JMS’s (for example it does it magic on the 2nd frame) but it goes the extra mile informing you what to expect.
Without any further aldo, here are the tests results:

The upper left image is the default suzanne with the normal-map-material, straight from the 2.36 release notes page.
The upper right image is the UV layout, in other words, how I unwrapped Suzzane.
The lower row is what you (finally) get with both scripts. Plese note that the scripts where not applied to the original Suzanne but to a very hight resultion version of her, the one used to generate the normal maps has 31,658 vertex.
At first sight, it looks like Nick’s map is wrong around the eyes area, but if you overlay the UV layout, you’ll see that it is totally fine and usable.
THE VEREDICT: They are both very good on their job. It is now a matter of personal taste witch one you’ll use.
BTW, Nick, I took the liberty of doing a small modification to your script, so that now the instructions show up in the Help-> “Script Help Browser” window, and also for it to show in the UV sub-menu. 
#!BPY
"""
Name: 'Bake Procedural Textures'
Blender: 234
Group: 'UV'
Tooltip: 'Bake procedural textures to image using UV coordinates.'
"""
## public domain
## author: z3r0_d (Nick Winters)
## no warranty (duh)
__author__ = "z3r0_d (Nick Winters)"
__bpydoc__ = """\
z3r0_d's TEXTURE BAKING SCRIPT
(better than jms's, for the moment)
INSTRUCTIONS:
1. select UV Mapped object with Procedural [material] textures
NOTE: only UV, Orco, Stick, Nor and Refl mapped textures will
work properly
NOTE 2: materials can be linked to object or mesh data, this
script will only use the material linked to mesh data,
regardless of which is active
2. run script [alt+p in text window, or run it from the 3d view's
Object menu, submenu Scripts]
3. configure render settings for square render:
aspect X and Y at 1, sizes at equal values
4. render [currently any frame other than #1], save, enjoy
5. if you don't want to tweak your material settings,
feel free to delete the objects that were created:
9 meshes and a camera, furthest on the positive X axis
[rightmost in top view]
consider using the "Full Osa" material option if your material looks
aliased [also, you need to turn OSA on]
"""
import Blender
from math import sqrt
UVMULTIPLIER = 8 ## higher values result in shorter uv extensions
UVDECIMALS = 4 ## rounding for uv coordinates doubles testing for corners [remove-doubles like behavior]
# todo:
# allow for materials linked to object instead of ME [mesh is default]
# allow rendering of frames other than #1
def copyVert(v):
nv = Blender.NMesh.Vert()
for j in range(3):
nv.co[j] = v.co[j]
nv.no[j] = v.no[j]
# I changed the meaning of the selection
#nv.sel = v.sel
for j in range(2): nv.uvco[j] = v.uvco[j]
return nv
def uvUnfold(obj):
print "BEGIN UV UNFOLDING NEW OBJECT GOODNESS"
odata = obj.getData()
# try to copy the mesh into a new object
nobj = Blender.NMesh.PutRaw(odata,"UF."+odata.name)
i = 0
while not nobj:# mesh with that name already exists... [in future I may want to overwrite it]
nobj = Blender.NMesh.PutRaw(odata,"UF."+odata.name+".%03i"%(i,))
# no longer needed, lets save some memory
del(odata)
del(obj)
ndata = nobj.getData()
ndata.hasVertexColours(1)
ndata.hasFaceUV(1)
ndata.removeAllKeys()
ndata.update()
# unselect all verts
# selected verts will be the new verts on the extruded uv edges
for v in ndata.verts: v.sel = 0
# create the uv seams, this is an inefficent [vertex wise, it is fast tho] method used here
numStartFaces = len(ndata.faces)
# dictionary of edges, key: tuple of 2 verts, value: list of faces which use this edge
# used to determine which edges are uv seams
#
# the same list object should be used for key (vert1, vert2) as key (vert2, vert1)
edges = {}
for f in ndata.faces[:numStartFaces]:
nv = len(f.v)
for vi in range(nv):
if edges.has_key( (f.v[vi], f.v[(vi+1)%nv]) ):
edges[(f.v[vi], f.v[(vi+1)%nv])].append(f)
else:
edges[(f.v[vi], f.v[(vi+1)%nv])] = [f]
edges[(f.v[(vi+1)%nv], f.v[vi])] = edges[(f.v[vi], f.v[(vi+1)%nv])]
# create the seam faces, these are used so the seams on the resulting texture are less visible
print "CREATING EXTRA UV SEAM FACES STEP 1"
overlapWarning = 0
# key: uv coordinate
# value: list of faces
# this will contain all uvs on seams, iff the number of faces is not 2, it is a corner
uv_corners = {}
for edge in edges.keys():
faces = edges[edge]
# this will contain every pair of 2 uv coords used in faces that used the edge
uvcoords = []
numUVedgeUsers = []
for f in faces:
# add the uvcoords used for edge into the list
myuvco = (f.uv[f.v.index(edge[0])],f.uv[f.v.index(edge[1])])
new_uv = 0
for i in range(len(uvcoords)):
if uvcoords[i] == myuvco:
new_uv = 1
break
if not new_uv:
uvcoords.append(myuvco)
numUVedgeUsers.append(1)
# I need to create new faces, several faces are on edges
# if mesh has 3 or more faces on this edge, it is possible only one is at a uv edge
# however, i will be more flexible than that
#
# find uv edges that are only used once
if len(uvcoords) >= len(faces): # is a uv seam
for f in faces:
# should be myuvcos, is two uv coordinates
myuvco = (f.uv[f.v.index(edge[0])],f.uv[f.v.index(edge[1])])
# for uv corners, add f to corresponding uv coords values if not already there
for i in (0,1):
# rounded uv coordinate...
ruvco = (round(myuvco[i][0],UVDECIMALS),round(myuvco[i][1],UVDECIMALS))
if uv_corners.has_key(ruvco) == 0: uv_corners[ruvco] = [f]
elif uv_corners[ruvco].count(f) == 0: uv_corners[ruvco].append(f)
uvIndex = uvcoords.index(myuvco)
if numUVedgeUsers[uvIndex] == 1:
nv1 = copyVert(edge[0])
nv2 = copyVert(edge[1])
nv1.sel = 1
nv2.sel = 1
ndata.verts.append(nv1)
ndata.verts.append(nv2)
# start off the new face as a copy of f
nf = Blender.NMesh.Face()
nf.v = [edge[0],edge[1],nv2,nv1]
## why I can't just set nf.col to [f.col[f.v.index(some vertex),more of the same] is beyond me
## well, I don't understand why none of these work
nf.col = [Blender.NMesh.Col(*rgbatuple) for rgbatuple in [(col.r, col.g, col.b, col.a) for col in [f.col[f.v.index(rvert)] for rvert in [edge[0],edge[1],edge[1],edge[0]] ]]]
nf.flag = f.flag
if f.image:
nf.image = f.image
nf.materialIndex = f.materialIndex
##nf.no = f.no#doesn't seem to work, shouldn't be necescary anyway
nf.smooth = f.smooth
nf.mode = f.mode
nf.transp = f.transp
nf.uv = [(0.0,0.0),(0.0,0.0),(0.5,0.5),(0.5,0.5)]
nf.uv[0] = myuvco[0]
nf.uv[1] = myuvco[1]
#
nf.uv[3] = nf.uv[0]
nf.uv[2] = nf.uv[1]
reverse = not (f.v.index(edge[1])+1)%len(f.v) != f.v.index(edge[0])
if reverse: reverse = -1
else: reverse = 1
uvco1 = f.uv[(f.v.index(edge[0])-reverse)%len(f.v)]
uvco2 = f.uv[f.v.index(edge[0])]
uvco3 = f.uv[f.v.index(edge[1])]
uvco4 = f.uv[(f.v.index(edge[1])+reverse)%len(f.v)]
vec1 = [uvco2[0] - uvco1[0], uvco2[1] - uvco1[1]]
vec2 = [uvco3[0] - uvco4[0], uvco3[1] - uvco4[1]]
## the value of UVMULTIPLIER on the next lines seems okay
## and it will be used for traingles too
len_vec1 = UVMULTIPLIER* sqrt(vec1[0]*vec1[0] + vec1[1]*vec1[1])
len_vec2 = UVMULTIPLIER* sqrt(vec2[0]*vec2[0] + vec2[1]*vec2[1])
if len_vec1 != 0.0: vec1 = [vec1[0] / len_vec1, vec1[1] / len_vec1]
if len_vec2 != 0.0: vec2 = [vec2[0] / len_vec2, vec2[1] / len_vec2]
nf.uv[3] =(nf.uv[0][0] + vec1[0], nf.uv[0][1] + vec1[1])
nf.uv[2] = (nf.uv[1][0] + vec2[0], nf.uv[1][1] + vec2[1])
# flip the quad, so normals are more right [in case they turn off no v. normal flip]
if (f.v.index(edge[1])+1)%len(f.v) != f.v.index(edge[0]):
# the quad needs to be flipped
for i in [0,2]:
# swap the verticies
tv = nf.v[i]
nf.v[i] = nf.v[i+1]
nf.v[i+1] = tv
# swap the uv coordinates
tuv = nf.uv[i]
nf.uv[i] = nf.uv[i+1]
nf.uv[i+1] = tuv
# swap the colors
tc = nf.col[i]
nf.col[i] = nf.col[i+1]
nf.col[i+1] = tc
# that ought to be it
ndata.faces.append(nf)
elif numUVedgeUsers[uvIndex] > 2 and not overlapWarning:
print "SHARED UVs!? SHAME ON YOU!!!", numUVedgeUsers[uvIndex], uvIndex
overlapWarning = 1
# so I don't create new faces on the edge twice
edges[edge] = []
edges[(edge[1],edge[0])] = edges[edge]
print "CREATING EXTRA UV SEAM FACES STEP 2"
# corner method:
"""
create a dictionary associating verticies with the faces they are contained in
[in the above loop?]
something about uv seams... [if that vert exists in a uv seam]
add the triangle extrusion for that vert, on each of the faces that contain it
and have the uv coordinate the seams is on
so, perhaps the key should be the NMVert and the Uv Coord?
"""
# create the corner faces
for myuv in uv_corners.keys():
if len(uv_corners[myuv]) == 2: continue # limit unnecescary corner triangles
for f in uv_corners[myuv]:
#indx = f.uv.index(myuv) ## can't be used as coordinate was rounded
indx = 5 # invalid
for uvenum in enumerate(f.uv):
if round(uvenum[1][0],UVDECIMALS) == myuv[0] and \
round(uvenum[1][1],UVDECIMALS) == myuv[1]:
indx = uvenum[0]
break
ntv1 = copyVert(f.v[indx])#copyVert(f.v[(indx+1)%len(f.v)])
ntv2 = copyVert(f.v[indx])#copyVert(f.v[(indx-1)%len(f.v)])
ntv1.sel = 1
ntv2.sel = 1
ndata.verts.append(ntv1)
ndata.verts.append(ntv2)
ntf = Blender.NMesh.Face()
ntf.v = [f.v[indx], ntv1, ntv2]
ntf.uv = [myuv, myuv, myuv]
# offset uv coordinates...
uvco1 = f.uv[(indx+1)%len(f.v)]
uvco2 = f.uv[indx]
uvco3 = f.uv[(indx-1)%len(f.v)]
#uvco4 = f.uv[(f.v.indx(edge[1])+reverse)%len(f.v)]
vec1 = [uvco2[0] - uvco1[0], uvco2[1] - uvco1[1]]
vec2 = [uvco3[0] - uvco2[0], uvco3[1] - uvco2[1]]
## the value of UVMULTIPLIER on the next lines seems okay
## and it will be used for traingles too
len_vec1 = UVMULTIPLIER* sqrt(vec1[0]*vec1[0] + vec1[1]*vec1[1])
len_vec2 = UVMULTIPLIER* sqrt(vec2[0]*vec2[0] + vec2[1]*vec2[1])
if len_vec1 != 0.0: vec1 = [vec1[0] / len_vec1, vec1[1] / len_vec1]
if len_vec2 != 0.0: vec2 = [vec2[0] / len_vec2, vec2[1] / len_vec2]
ntf.uv[1] =(ntf.uv[1][0] + vec1[0], ntf.uv[1][1] + vec1[1])
ntf.uv[2] = (ntf.uv[2][0] - vec2[0], ntf.uv[2][1] - vec2[1])
# more face property copying goodness
ntf.col = [Blender.NMesh.Col(*rgbatuple) for rgbatuple in [(col.r, col.g, col.b, col.a) for col in [f.col[vindex%len(f.v)] for vindex in [indx,indx+1,indx-1] ]]]
ntf.flag = f.flag
if f.image:
ntf.image = f.image
ntf.materialIndex = f.materialIndex
##ntf.no = f.no#doesn't seem to work, shouldn't be necescary anyway
ntf.smooth = f.smooth
ntf.mode = f.mode
ntf.transp = f.transp
#
##ndata.verts.extend([ntv1,ntv2])
ndata.faces.append(ntf)
# no longer needed, lets save some memory
del(edges)
del(uv_corners)
ndata.update()
# flag if I have done the vert yet
# [so I don't end up with unused verts in the resulting mesh]
donevert = list([0]*len(ndata.verts))
print "CREATING REQUIRED EXTRA FACES AT UV SEAMS STEP 3"
for f in ndata.faces:
i = 0
for v in f.v:
#print v.index, len(ndata.verts)
if donevert[v.index]:
# copy the vert
nv = copyVert(v)
ndata.verts.append(nv)
f.v[i] = nv
else:
donevert[v.index] = 1
i += 1
# no longer needed, lets save some memory
del(donevert)
ndata.update()
ndata.insertKey(1, 'absolute')
# now move the verts
print "MOVING VERTS TO UV COORDINATES"
for f in ndata.faces:
i = 0
for v in f.v:
v.co[0] = f.uv[i][0]*4.0-2.0
v.co[1] = f.uv[i][1]*4.0-2.0
v.co[2] = 0.0
if v.sel: v.co[2] = -0.01
i += 1
# just TwoSided
ndata.setMode("TwoSided")
ndata.update()
ndata.insertKey(2)
#not always necescary
nobj.makeDisplayList()
##Blender.Draw.Redraw()
return nobj
objs = Blender.Object.GetSelected()
if len(objs) > 0 and objs[0].getType()=="Mesh":
startTime = Blender.sys.time()
print
print "FINDING BOUNDS OF ALL OBJECTS",
# actually, I just want the highest X val so I can position the objects
# I create suitably far away [to the right]
maxX = -1000000000.0
objects = Blender.Object.Get()
for obj in objects:
# it is somewhat annoying, both empties and cameras should return None
# as their bound box, but emptys give errors, and cameras return none
if obj.getType() == "Empty" or not obj.getBoundBox(): continue
for vec in obj.getBoundBox(): # was this function introduced 2.33 or earlier?
if vec[0] > maxX: maxX = vec[0]
center = (maxX+6.0, 0.0, 0.0)
print "DONE"
scene = Blender.Scene.getCurrent()
centerobj = uvUnfold(objs[0])
centerobj.setLocation(*center)
# duplicate objects [for when uv may go off edge, or at least to allow extension to go off edge of tex]
for offset in [ (-1,1), (0,1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0) ]:
nobj = Blender.Object.New('Mesh')
nobj.shareFrom(centerobj)
nobj.setLocation(center[0] + 4.0*offset[0], center[1] + 4.0*offset[1], center[2])
scene.link(nobj)
# create the camera
cam = Blender.Camera.New('ortho')
# these values are larger than necescary, apparently the 3d view and render don't line up exactly
# the error caused by having these larger values isn't significant enough to bother
cam.setClipStart(1.0)
cam.setClipEnd(3.0)
# this is actually necescary for ortho cameras
cam.setLens(16.0)
camObj = Blender.Object.New('Camera')
camObj.setLocation(center[0], center[1], center[2]+2.0)
camObj.link(cam)
scene.link(camObj)
scene.setCurrentCamera(camObj)
print "took", Blender.sys.time() - startTime, "seconds"
print "######## SUCCESS ########"
if Blender.Get('curframe') == 1: Blender.Draw.PupMenu("Warning: Do not render frame number 1")
else:
if len(objs) == 0: Blender.Draw.PupMenu("Error: Nothing Selected")
elif objs[0].getType()!="Mesh": Blender.Draw.PupMenu("Error: Active object not a Mesh")