Batch Lightmap for Unity

I am currently working on a script that will allow me to do prepare models for unity game engine. This mostly deals with setting up baked textures and lighting. So I basically see this as a three step process.

  1. Prepare selected objects for baking
    1a. First, check for UVLayers of object(s), clean if wanted, then add a new lightmap layer
    1b. Next, set the lightmap layer as active UVLayer
    1c. Finally, create a new lightmap image for the baking process

  2. Bake your selected objects

  3. Save images of selected objects to pngs

I have written the code for most of part 1 (below). However the biggest problem I have is that I have not found a way to purge old images. As a result, the images just continue to build and build into the file. Well here is the code below:

Updated Code Below - 11/10/09 - See post #3 for comments and tips
Sorry for no UI, be sure the options match between the Setup and Save scripts for best use.


import Blender
from Blender import Draw,Image,Material,Mesh,Object,Texture,Types
import bpy
import uvcalc_smart_project

######## Options to Change #########
LIGHTMAP_SIZE=1024
FILE_SUFFIX='LM'
FILE_PREFIX='A_'
UVLAYER_NAME='Lightmap'
CLEAR_UVLAYERS=0
CLEAR_IMAGES=0
####################################


BLEND_FILE=Blender.Get('filename')

print BLEND_FILE
#Get all selected objects
ob_list = Blender.Object.GetSelected()

#CLEANING THE IMAGE FILES
if CLEAR_IMAGES == 1:
    for m in ob_list:
        for f in m.getData(mesh=1).faces:
            image = None
            try: image = f.image
            except: pass
            if image:
                bImageReplacePointer = []
                replaceImage = bImageReplacePointer
                f.image = None
            
        

#Go through every object
for i in ob_list:
    mesh_data = i.getData(mesh=1)
    has_image = mesh_data.faceUV
    print '____________Working on %s ____________' % mesh_data.name
    
    #Delete all UVLayers if required
    if CLEAR_UVLAYERS==1 and mesh_data.getUVLayerNames():
        print "Cleaning out old UV layers"
        for layer in mesh_data.getUVLayerNames():
            mesh_data.removeUVLayer(layer)
            print "Deleted UVLayer: %s" % layer
    
    #Test to see if uvlayer already exists
    lm_exists = [o for o in mesh_data.getUVLayerNames() if o == UVLAYER_NAME]
    if not lm_exists:
        mesh_data.addUVLayer(UVLAYER_NAME)
        
    #Make Lightmap the active UVLayer
    mesh_data.activeUVLayer=UVLAYER_NAME
    
    #Create a new image for the faces in the object
    #See if image with name already exists
    lmimg_exists = [o.name for o in Blender.Image.Get() if o.name == FILE_PREFIX+i.name+"_"+FILE_SUFFIX ]
    print "Testing to see if image %s exists..." % lmimg_exists
    
    if lmimg_exists:
        print "Image %s alredy exists. Renaming, unlinking, and creating new image..." % (FILE_PREFIX+mesh_data.name+"_"+FILE_SUFFIX)
        Image.Get(FILE_PREFIX+i.name+"_"+FILE_SUFFIX).setName("Purged")
        
        blankImg = None
        blankImg=Image.New(FILE_PREFIX+i.name+"_"+FILE_SUFFIX,LIGHTMAP_SIZE,LIGHTMAP_SIZE,24)
        for f in mesh_data.faces:
            f.sel=1
            f.image=blankImg
        
    if not lmimg_exists:
        print "Image %s does not exist. Creating..." % (FILE_PREFIX+i.name+"_"+FILE_SUFFIX)
        blankImg=None
        blankImg=Image.New(FILE_PREFIX+i.name+"_"+FILE_SUFFIX,LIGHTMAP_SIZE,LIGHTMAP_SIZE,24)
        for f in mesh_data.faces:
            f.sel=1
            f.image=blankImg
    mesh_data.update()
    
# In uvcalc_smart_project.py, if the active object is NOT selected,
# it would be the only one processed, replacing all currently selected objects.
# Here is the stupid code :
#        ob = objects.active
#        if ob and ob.sel == 0 and ob.type == 'Mesh':
#            # Add to the list
#            obList =[ob]   <---- WT* ? "Add to the list" it says ? LOL
# So, just clear unselected active object before proceed.
objs=bpy.data.scenes.active.objects
activeObj=objs.active
if activeObj and activeObj.sel==0:
    objs.active=None
# unwrap UV, use the smart one, to minimize overlapping faces
uvcalc_smart_project.main()


####### Image Save Script ########
import Blender
from Blender import Draw,Image,Material,Mesh,Object,Texture,Types
import bpy
import uvcalc_smart_project

######## Options to Change #########
FILE_SUFFIX='AO'
FILE_PREFIX='A_'
UVLAYER_NAME='AO'
SAVE_DIR='C:\Users\Ryan\Desktop\Unity_a\Assets\Textures\\'
####################################


BLEND_FILE=Blender.Get('filename')

print BLEND_FILE
#Get all selected objects
ob_list = Blender.Object.GetSelected()

for m in ob_list:
    saved = 0
    for f in m.getData(mesh=1).faces:
        if saved == 0:
            image = f.image
            save_name = SAVE_DIR+image.name+'.tga'
            print save_name
            
            lmimg_exists = [o.name for o in Blender.Image.Get() if o.name == save_name ]
            
            if lmimg_exists:
                for h in m.getData(mesh=1).faces:
                    Image.Get(save_name).setName("Purged")
                image.setFilename(save_name)
                image.save()
                img = Image.Load(save_name)
                
            if not lmimg_exists:
                image.setFilename(save_name)
                image.save()
                img = Image.Load(save_name)

            saved = saved+1
        print img
        f.image=img

This final script is an image unlinker. It should unlink every image associated with the selected objects. Consider it a nuclear option, and use at your own risk. After using, please save & open, save & open to be sure all image data has been removed.


####### Image Unlinker #######

import Blender
from Blender import Draw,Image,Material,Mesh,Object,Texture,Types
import bpy
import uvcalc_smart_project


#Get all selected objects
ob_list = Blender.Object.GetSelected()

for m in ob_list:
    for f in m.getData(mesh=1).faces:
        image = None
        try: image = f.image
        except: pass
        if image:
            bImageReplacePointer = []
            replaceImage = bImageReplacePointer
            f.image = None

I don’t think that images can be removed manually from a .blend file. (not positive, but I’m fairly sure) I think you have to just save and close the file, and they will be gone if nothing is using them when you reopen it. Why do you need to delete them? Are you sure nothing else is using these images?

Ok, images cannot simply be removed from a file, however you can unlink them all, then all one needs to do is save, open, save open and they will be cleaned. I have updated the scripts in the first post to show the progress.

This is currently a three step process for each set of images you would like to bake.

  1. Select all meshes and run the bakesetup script. This will create the new UV layer, and a new image of the size you want. Then it will unwrap the mesh within the object.

  2. Then you will bake the selected meshes with which ever bake you are trying for. AO, full, shadow, etc.

  3. Use the imagesave script to save the images you just baked.

  4. Repeat 1-3 for each set of bakes you wanted to do. I have been baking a AO bake and a shadow bake, which I combine later.

Please pay attention to the Options at the top of each page, be sure that they are consistent between the Setup and Save script. These scripts are by no means polished or finished, but they are serviceable and do their job as this point. Hopefully, they could be useful to someone else.

Let me know if you have any questions or comments.

I REALLY need this stuff.Thanks a lot.I’m gonna testing…

I was not sure that anyone was interested in this. I dig around and post my newest versions of the files I am using in the next day or so.

Do you then linkthe lightmaps in unity? or do you need to assign to materials in blender?