diff options
author | Campbell Barton <ideasman42@gmail.com> | 2006-05-30 14:15:01 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2006-05-30 14:15:01 +0400 |
commit | a7c61f96f676b94cdd30d55f39fad9b1bd41ab5b (patch) | |
tree | 5cfabfb3493bf76a3508961a7ee7e62aee54b888 /release | |
parent | 4a0d7039640774ed53b761384d2ccd5979a63064 (diff) |
Braught back saveRenderedImage now I have a clue about what it does.
Cleaned up functions and optimized loops, extra checks and better defaults.
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/uv_auto_layout_tex.py | 199 |
1 files changed, 96 insertions, 103 deletions
diff --git a/release/scripts/uv_auto_layout_tex.py b/release/scripts/uv_auto_layout_tex.py index 1e8e97cdbed..c707abf7316 100644 --- a/release/scripts/uv_auto_layout_tex.py +++ b/release/scripts/uv_auto_layout_tex.py @@ -35,7 +35,7 @@ This is usefull for game models where 1 image is faster then many, and saves the # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# +# f # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- @@ -46,37 +46,57 @@ import boxpack2d from Blender.Mathutils import Vector, RotationMatrix from Blender.Scene import Render import BPyMathutils +BIGNUM= 1<<30 - -''' -RotMatStepRotation = [] -rot_angle = 22.5 -while rot_angle > 0.1: - RotMatStepRotation.append([\ - (rot_angle, RotationMatrix( rot_angle, 2)),\ - (-rot_angle, RotationMatrix( -rot_angle, 2))]) - rot_angle = rot_angle/2.0 -''' - -def pointBoundsArea(points): - x= [p.x for p in points] # Lazy use of LC's - y= [p.y for p in points] - return (max(x)-min(x)) * (max(y)-min(y)) +def pointBounds(points): + ''' + Takes a list of points and returns the + area, center, bounds + ''' + ymax= xmax= -BIGNUM + ymin= xmin= BIGNUM + + for p in points: + x= p.x + y= p.y + + if x>xmax: xmax=x + if y>ymax: ymax=y + + if x<xmin: xmin=x + if y<ymin: ymin=y + + # area and center + return\ + (xmax-xmin) * (ymax-ymin),\ + Vector((xmin+xmax)/2, (ymin+ymax)/2),\ + (xmin, ymin, xmax, ymax) def bestBoundsRotation(current_points): - current_area= pointBoundsArea(current_points) + ''' + Takes a list of points and returns the best rotation for those points + so they fit into the samllest bounding box + ''' + + current_area, cent, bounds= pointBounds(current_points) - main_rot_angle= 0.0 - rot_angle= 45.0 + total_rot_angle= 0.0 + rot_angle= 45 while rot_angle > 0.1: mat_pos= RotationMatrix( rot_angle, 2) mat_neg= RotationMatrix( -rot_angle, 2) new_points_pos= [v*mat_pos for v in current_points] - new_points_neg= [v*mat_neg for v in current_points] - area_pos= pointBoundsArea(new_points_pos) - area_neg= pointBoundsArea(new_points_neg) + area_pos, cent_pos, bounds_pos= pointBounds(new_points_pos) + + # 45d rotations only need to be tested in 1 direction. + if rot_angle == 45: + area_neg= area_pos + else: + new_points_neg= [v*mat_neg for v in current_points] + area_neg, cent_neg, bounds_neg= pointBounds(new_points_neg) + # Works! #print 'Testing angle', rot_angle, current_area, area_pos, area_neg @@ -84,74 +104,56 @@ def bestBoundsRotation(current_points): best_area= min(area_pos, area_neg, current_area) if area_pos == best_area: current_area= area_pos + cent= cent_pos + bounds= bounds_pos current_points= new_points_pos - main_rot_angle+= rot_angle - elif area_neg == best_area: + total_rot_angle+= rot_angle + elif rot_angle != 45 and area_neg == best_area: current_area= area_neg + cent= cent_neg + bounds= bounds_neg current_points= new_points_neg - main_rot_angle-= rot_angle + total_rot_angle-= rot_angle rot_angle *= 0.5 # Return the optimal rotation. - return main_rot_angle + return total_rot_angle + -BIGNUM= 1<<30 class faceGroup(object): + ''' + A Group of faces that all use the same image, each group has its UVs packed into a square. + ''' __slots__= 'xmax', 'ymax', 'xmin', 'ymin',\ 'image', 'faces', 'box_pack', 'size', 'ang', 'rot_mat', 'cent'\ def __init__(self, mesh_list, image, size, PREF_IMAGE_MARGIN): self.image= image self.size= size + self.faces= [f for me in mesh_list for f in me.faces if f.image == image] # Find the best rotation. - all_points= [Vector(uv) for me in mesh_list for f in me.faces for uv in f.uv if f.image==image] - boundry_indicies= BPyMathutils.convexHull(all_points) - bountry_points= [all_points[i] for i in boundry_indicies] - - # Yay this works. - self.ang= bestBoundsRotation(bountry_points) - self.rot_mat= RotationMatrix(self.ang, 2), RotationMatrix(-self.ang, 2), + all_points= [uv for f in self.faces for uv in f.uv] + bountry_indicies= BPyMathutils.convexHull(all_points) + bountry_points= [all_points[i] for i in bountry_indicies] - #print 'ANGLE', image.name, ang - - # Add to our face group and set bounds. - # Find the centre - xmin=ymin= BIGNUM - xmax=ymax= -BIGNUM - self.faces= [] - for me in mesh_list: - for f in me.faces: - if f.image==image: - self.faces.append(f) - for uv in f.uv: - #uv= uv * self.rot_mat - - xmax= max(xmax, uv.x) - xmin= min(xmin, uv.x) - ymax= max(ymax, uv.y) - ymin= min(ymin, uv.y) - - self.cent= Vector((xmax-xmin)/2, (ymax+ymin)/2 ) - - # now get the bounds after rotation about the cent. - xmin=ymin= BIGNUM - xmax=ymax= -BIGNUM - for f in self.faces: - for uv in f.uv: - uv= ((uv-self.cent) * self.rot_mat[0]) + self.cent - xmax= max(xmax, uv.x) - xmin= min(xmin, uv.x) - ymax= max(ymax, uv.y) - ymin= min(ymin, uv.y) + # Pre Rotation bounds + self.cent= pointBounds(bountry_points)[1] + # Get the optimal rotation angle + self.ang= bestBoundsRotation(bountry_points) + self.rot_mat= RotationMatrix(self.ang, 2), RotationMatrix(-self.ang, 2) - # The box pack list is to be passed to the external function "boxpack2d" - # format is ID, w,h + # Post rotation bounds + bounds= pointBounds([\ + ((uv-self.cent) * self.rot_mat[0]) + self.cent\ + for uv in bountry_points])[2] + # Break the bounds into useable values. + xmin, ymin, xmax, ymax= bounds - # Store the bounds, impliment the margin. + # Store the bounds, include the margin. # The bounds rect will need to be rotated to the rotation angle. self.xmax= xmax + (PREF_IMAGE_MARGIN/size[0]) self.xmin= xmin - (PREF_IMAGE_MARGIN/size[0]) @@ -163,7 +165,6 @@ class faceGroup(object): size[0]*(self.xmax - self.xmin),\ size[1]*(self.ymax - self.ymin)] - ''' # default. self.scale= 1.0 @@ -202,31 +203,30 @@ class faceGroup(object): uv.y= offset_y+ (((uv_rot.y-self.ymin) * self.size[1])/height) def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN): #, PREF_SIZE_FROM_UV=True): - - # Get all images used by the mesh + '''Main packing function''' face_groups= {} for me in mesh_list: for f in me.faces: - if f.image: + image= f.image + if image: try: - face_groups[f.image.name] # will fail if teh groups not added. + face_groups[image.name] # will fail if teh groups not added. except: - image= f.image try: size= image.size except: B.Draw.PupMenu('Aborting: Image cold not be loaded|' + image.name) return - face_groups[f.image.name]= faceGroup(mesh_list, f.image, size, PREF_IMAGE_MARGIN) + face_groups[image.name]= faceGroup(mesh_list, image, size, PREF_IMAGE_MARGIN) if not face_groups: B.Draw.PupMenu('No Images found in mesh. aborting.') return - if len(face_groups)==1: - B.Draw.PupMenu('Only 1 image found|use meshes using 2 or more images.') + if len(face_groups)<2: + B.Draw.PupMenu('Only 1 image found|Select a mesh using 2 or more images.') return ''' @@ -239,17 +239,11 @@ def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ render_scn= B.Scene.New() render_scn.makeCurrent() render_context= render_scn.getRenderingContext() - render_context.endFrame(1) - render_context.startFrame(1) - render_context.currentFrame(1) - render_context.setRenderPath(PREF_IMAGE_PATH) - - # Set the render context - PREF_IMAGE_PATH_EXPAND= B.sys.expandpath(PREF_IMAGE_PATH+'#') + '.png' + render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path. + PREF_IMAGE_PATH_EXPAND= B.sys.expandpath(PREF_IMAGE_PATH) + '.png' # TEST THE FILE WRITING. - ''' try: # Can we write to this file??? f= open(PREF_IMAGE_PATH_EXPAND, 'w') @@ -257,7 +251,6 @@ def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ except: B.Draw.PupMenu('Error: Could not write to path|' + PREF_IMAGE_PATH_EXPAND) return - ''' render_context.imageSizeX(PREF_IMAGE_SIZE) render_context.imageSizeY(PREF_IMAGE_SIZE) @@ -297,10 +290,9 @@ def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ # Position the camera - render_cam_ob.LocZ= 1.0 # set back 1 - render_cam_ob.LocX= 0.5 # set back 1 - render_cam_ob.LocY= 0.5 # set back 1 - #render_cam_ob.RotY= 180 * 0.017453292519943295 # pi/180.0 + render_cam_ob.LocZ= 1.0 + render_cam_ob.LocX= 0.5 + render_cam_ob.LocY= 0.5 # List to send to to boxpack function. boxes2Pack= [ fg.box_pack for fg in face_groups.itervalues()] @@ -360,22 +352,21 @@ def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ for c in target_face.col: c.r= c.g= c.b= 255 - #render_context.render() - - render_context.renderAnim() + render_context.render() Render.CloseRenderWindow() + render_context.saveRenderedImage(PREF_IMAGE_PATH_EXPAND) - #print 'attempting to save an image', PREF_IMAGE_PATH_EXPAND - - #render_context.saveRenderedImage(PREF_IMAGE_PATH_EXPAND) - - #if not B.sys.exists(PREF_IMAGE_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 - target_image= B.Image.Load(PREF_IMAGE_PATH_EXPAND) + try: + target_image= B.Image.Load(PREF_IMAGE_PATH_EXPAND) + except: + B.Draw.PupMenu('Error: Could not render or load the image at path|' + PREF_IMAGE_PATH_EXPAND) + return # Set to the 1 image. for me in mesh_list: @@ -388,6 +379,7 @@ def auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ scn.makeCurrent() B.Scene.Unlink(render_scn) + render_me.verts= None # free a tiny amount of memory. def main(): @@ -403,13 +395,13 @@ def main(): newpath= B.Get('filename').split('/')[-1].split('\\')[-1].replace('.blend', '') PREF_IMAGE_PATH = B.Draw.Create('//%s_grp' % newpath) - PREF_IMAGE_SIZE = B.Draw.Create(512) + PREF_IMAGE_SIZE = B.Draw.Create(1024) PREF_IMAGE_MARGIN = B.Draw.Create(6) - PREF_KEEP_ASPECT = B.Draw.Create(1) + PREF_KEEP_ASPECT = B.Draw.Create(0) PREF_ALL_SEL_OBS = B.Draw.Create(0) pup_block = [\ - 'image path: no ext',\ + '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.'),\ @@ -437,6 +429,7 @@ def main(): mesh_list= [ob.getData(mesh=1)] auto_layout_tex(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN) - + B.Window.RedrawAll() + if __name__=='__main__': main() |