Added a script that makes an image from vertex colors using UV coords. the advantage this has over other existing scripts is that it bleeds the colors from edge polygons so you dont get mipmapping errors.

usefull for baking radiosity back into an image (with non overlapping UV's) and also has an option for including the texface image, and using normals (instead of colors)

Added BPyRender with a utility function to render off an ortho image from a number of objects.
This commit is contained in:
Campbell Barton
2006-07-26 02:07:12 +00:00
parent 1bf883b799
commit c03179c9b3
2 changed files with 230 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
from Blender import Scene, sys, Camera, Object, Image
from Blender.Scene import Render
def imageFromObjectsOrtho(objects, path, width, height, alpha= True):
'''
Takes any number of objects and renders them on the z axis, between x:y-0 and x:y-1
Usefull for making images from a mesh without per pixel operations
- objects must be alredy placed
- path renders to a PNG image
'''
# remove an extension if its alredy there
if path.lower().endswith('.png'):
path= path[:-4]
path_expand= sys.expandpath(path) + '.png'
# Touch the path
try:
f= open(path_expand, 'w')
f.close()
except:
raise 'Error, could not write to path'
# RENDER THE FACES.
scn= Scene.GetCurrent()
render_scn= Scene.New()
render_scn.makeCurrent()
# Add objects into the current scene
for ob in objects:
render_scn.link(ob)
# set layers
render_context= render_scn.getRenderingContext()
render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path.
render_context.imageSizeX(width)
render_context.imageSizeY(height)
render_context.enableOversampling(True)
render_context.setOversamplingLevel(16)
render_context.setRenderWinSize(100)
render_context.setImageType(Render.PNG)
render_context.enableExtensions(True)
#render_context.enableSky() # No alpha needed.
if alpha:
render_context.alphaMode= 2
render_context.enableRGBAColor()
else:
render_context.alphaMode= 0
render_context.enableRGBColor()
render_context.displayMode= 0 # fullscreen
# New camera and object
render_cam_data= Camera.New('ortho')
render_cam_ob= Object.New('Camera')
render_cam_ob.link(render_cam_data)
render_scn.link(render_cam_ob)
render_scn.setCurrentCamera(render_cam_ob)
render_cam_data.type= 1 # ortho
render_cam_data.scale= 1.0
# Position the camera
render_cam_ob.LocZ= 1.0
render_cam_ob.LocX= 0.5
render_cam_ob.LocY= 0.5
render_context.render()
#Render.CloseRenderWindow()
render_context.saveRenderedImage(path)
#if not B.sys.exists(PREF_IMAGE_PATH_EXPAND):
# raise 'Error!!!'
# NOW APPLY THE SAVED IMAGE TO THE FACES!
#print PREF_IMAGE_PATH_EXPAND
try:
target_image= Image.Load(path_expand)
except:
raise 'Error: Could not render or load the image at path "%s"' % path_expand
return
#scn.makeCurrent()
#Scene.Unlink(render_scn)

View File

@@ -0,0 +1,140 @@
#!BPY
"""
Name: 'Color/Normals to Image'
Blender: 241
Group: 'UV'
Tooltip: 'Save the active meshes vertex colors or normals to an image.'
"""
__author__= ['Campbell Barton']
__url__= ('blender', 'elysiun', 'http://www.gametutorials.com')
__version__= '0.95'
__bpydoc__= '''\
Vert color to Image
This script makes an image from a meshes vertex colors, using the UV coordinates
to draw the faces into the image.
This makes it possible to bake radiosity into a texture.
Make sure your UV Coordinates do not overlap. LSCM Unwrapper or archimap unwrapper work well
to automaticaly do this.
'''
import Blender
import BPyRender
reload(BPyRender)
import BPyMesh
Vector= Blender.Mathutils.Vector
Create= Blender.Draw.Create
def rnd_mat():
render_mat= Blender.Material.New()
render_mat.mode |= Blender.Material.Modes.VCOL_PAINT
render_mat.mode |= Blender.Material.Modes.SHADELESS
render_mat.mode |= Blender.Material.Modes.TEXFACE
return render_mat
def vcol2image(me, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_IMAGE_BLEED, PREF_USE_IMAGE, PREF_USE_NORMAL):
BLEED_PIXEL= 1.0/PREF_IMAGE_SIZE
if PREF_USE_NORMAL:
BPyMesh.meshCalcNormals(me)
render_me= Blender.Mesh.New()
render_me.verts.extend( [Vector(0,0,0),] )
render_me.verts.extend( [ Vector(uv.x-BLEED_PIXEL, uv.y-BLEED_PIXEL/2, 0) for f in me.faces for uv in f.uv ] )
i= 1
tmp_faces= []
for f in me.faces:
tmp_faces.append( [ii+i for ii in xrange(len(f))] )
i+= len(f)
render_me.faces.extend(tmp_faces)
for i, f in enumerate(me.faces):
frnd= render_me.faces[i]
if PREF_USE_IMAGE:
ima= f.image
if ima:
frnd.image= ima
frnd.uv= f.uv
if PREF_USE_NORMAL:
for ii, v in enumerate(f.v):
no= v.no
c= frnd.col[ii]
c.r= int((no.x+1)*128)-1
c.g= int((no.y+1)*128)-1
c.b= int((no.z+1)*128)-1
else:
frnd.col= f.col
render_ob= Blender.Object.New('Mesh')
render_ob.link(render_me)
obs= [render_ob]
# EVIL BLEEDING CODE!! - Just do copys of the mesh and place behind. Crufty but better then many other methods I have seen.
if PREF_IMAGE_BLEED:
z_offset= 0.0
for i in xrange(PREF_IMAGE_BLEED):
for diag1, diag2 in ((-1,-1),(-1,1),(1,-1),(1,1), (1,0), (0,1), (-1,0), (0, -1)): # This line extends the object in 8 different directions, top avoid bleeding.
render_ob= Blender.Object.New('Mesh')
render_ob.link(render_me)
render_ob.LocX= (i+1)*diag1*BLEED_PIXEL
render_ob.LocY= (i+1)*diag2*BLEED_PIXEL
render_ob.LocZ= -z_offset
obs.append(render_ob)
z_offset += 0.01
render_me.materials= [rnd_mat()]
im= BPyRender.imageFromObjectsOrtho(obs, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_IMAGE_SIZE)
def main():
# Create the variables.
# Filename without path or extension.
scn= Blender.Scene.GetCurrent()
act_ob= scn.getActiveObject()
if not act_ob or act_ob.getType() != 'Mesh':
Blender.Draw.PupMenu('Error, no active mesh selected.')
return
newpath= Blender.Get('filename').split('/')[-1].split('\\')[-1].replace('.blend', '')
PREF_IMAGE_PATH = Create('//%s_grp' % newpath)
PREF_IMAGE_SIZE = Create(1024)
PREF_IMAGE_BLEED = Create(6)
PREF_USE_IMAGE = Create(0)
PREF_USE_NORMAL = Create(0)
pup_block = [\
'Image Path: (no ext)',\
('', PREF_IMAGE_PATH, 3, 100, 'Path to new Image. "//" for curent blend dir.'),\
'Image Options',
('Pixel Size:', PREF_IMAGE_SIZE, 64, 4096, 'Image Width and Height.'),\
('Pixel Bleed:', PREF_IMAGE_BLEED, 0, 64, 'Image Bleed pixels.'),\
('Image Include', PREF_USE_IMAGE, 'Image Bleed pixels.'),\
'',\
('Normal Map', PREF_USE_NORMAL, 'Use Normals instead of VCols.'),\
]
if not Blender.Draw.PupBlock('VCol to Image', pup_block):
return
vcol2image(act_ob.getData(mesh=1), PREF_IMAGE_PATH.val, PREF_IMAGE_SIZE.val, PREF_IMAGE_BLEED.val, PREF_USE_IMAGE.val, PREF_USE_NORMAL.val)
Blender.Window.RedrawAll()
if __name__ == '__main__':
main()