home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2005 November / WNnov2005.iso / Windows / Equipement / Blender / blender-2.37a-windows.exe / $_5_ / .blender / scripts / tex2uvbaker.py < prev    next >
Text File  |  2005-06-13  |  16KB  |  499 lines

  1. #!BPY
  2.  
  3. """ Registration info for Blender menus:
  4. Name: 'Texture Baker'
  5. Blender: 237
  6. Group: 'UV'
  7. Tooltip: 'Procedural to uvmapped texture baker'
  8. """
  9.  
  10. __author__ = "Jean-Michel Soler (jms)"
  11. __url__ = ("blender", "elysiun",
  12. "Official Page, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm",
  13. "Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
  14. __version__ = "0.2.6 2005/5/29"
  15.  
  16. __bpydoc__ = """\
  17. Texture Baker "bakes" Blender procedural materials (including textures): it saves them as 2d uv-mapped images.
  18.  
  19. This script saves an uv texture layout of the chosen mesh, that can be used as
  20. an uv map for it.  It is a way to export procedurals from Blender as normal
  21. image textures that can be edited with a 2d image manipulation program or used
  22. with the mesh in games and other 3d applications.
  23.  
  24. Usage:
  25.  
  26. a) Enter face mode and define uv coordinates for your mesh (do not forget to choose a development shape);<br>
  27. b) Define its materials and textures;<br>
  28. c) Run this script and check the console.
  29.  
  30. Global variables:
  31.  
  32. a) FRAME (integer): the last frame of the animation, autodocumented.<br>
  33. b) LIMIT (integer): 0 or 1, uvcoords may exceed limits 0.0 to 1.0, this variable obliges the script to do a complete framing of the uvcoord.
  34.  
  35. Notes:<br>
  36.    This script was based on a suggestion by Martin (Theeth) Poirier.
  37. """
  38.  
  39. #---------------------------------------------
  40. # Last release : 0.2.6 ,  2005/05/29 , 22h00
  41. #---------------------------------------------
  42. #---------------------------------------------
  43. # (c) jm soler  07/2004 : 'Procedural Texture Baker'
  44. #     Based on a Martin 'Theeth' Poirier's really
  45. #     good idea : makes a rvk mesh with uv coords
  46. #     of the original mesh.
  47. #
  48. #     Released under Blender Artistic Licence
  49. #
  50. #   0.2.6
  51. #       -- Creation of LAMP object is removed and replaced
  52. #       by the use of the shadeless option  in material object
  53. #
  54. #       -- helpmsg corrected : the aim of the script
  55. #       is to bake any type of textures so we have not
  56. #       to mapinput its textures on UV .
  57. #
  58. #       --'pers' camera was replaced by an 'ortho' one. 
  59. #
  60. #   0.2.5
  61. #       -- if a image file  with the same name exits the
  62. #       system returns an error 
  63. #
  64. #   0.2.4
  65. #       -- a LIMIT variable is added to unlock the uvcoords
  66. #       autoframing
  67. #
  68. #
  69. #   0.2.3 :  
  70. #        Great thanks for Apollux  who sees a lot of these 
  71. #        problems
  72. #
  73. #        --Everytime you run the script a new set 
  74. #        of objects is created. File size and memory 
  75. #        consumption can go  pretty high if you are 
  76. #        not aware of that . 
  77. #        Now it ONLY creates 3 objects: a flattened 
  78. #         mesh, a camera and a lamp.
  79. #        --all the 3 objects was placed on layer 1, but if 
  80. #        that layer was not visible while you used the script 
  81. #        all you will get a is an empty render. 
  82. #        Now the layer is tst and activated befor the shoot 
  83. #        --The flattened mesh was really flattend only after 
  84. #        frame 100 (if you playbacked the animation, you can 
  85. #        actually see the mesh becoming flat on the first 100 
  86. #        frames). No more.
  87. #        -- When the script is run, it changes temporary to 
  88. #        the new cammera, set the render output to a square 
  89. #        (i.e. 1024 x 1024 or else), does the render, and then 
  90. #        resets the render output and the active camera to the 
  91. #        original one. But if no original camera was found
  92. #        this produce an error.    
  93. #
  94. #  0.2.2 : 
  95. #        if the uv mesh objet exists it used,
  96. #        no creation of a new one. As the lamp and  
  97. #        the camera
  98. #  0.2.1 : 
  99. #        This script automaticaly frame and shoot the
  100. #        new uv mesh . The image file is saved ine the
  101. #        /render folder.
  102. #
  103. #---------------------------------------------
  104. #  On user-friendly side :
  105. #---------------------------------------------
  106. #- Tadje Vobovnik adds the Select Image Size Menu
  107. #
  108. #---------------------------------------------
  109. # Official Page :
  110. #  http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm
  111. # For problems and errors:
  112. #   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
  113. #---------------------------------------------
  114.  
  115. import Blender
  116. from Blender import NMesh, Draw, Object, Scene, Camera
  117.  
  118. #----------------------------------- 
  119. # Last release : 0.2.5 ,  2005/05/22 , 20h00
  120. #----------------------------------- 
  121. # la fonction Blender.sys.dirname pose un
  122. # probleme lorsque la memoire est trop encombree
  123. # ---
  124. # It seems that the Blender.sys.dirname function
  125. # poses a problem when the memory is too much encumbered 
  126. #----------------------------------- 
  127. try:
  128.   import nt
  129.   os = nt
  130.   os.sep='\\'
  131. except:
  132.   import posix
  133.   os = posix
  134.   os.sep='/'
  135. DIRNAME=Blender.Get('filename')
  136. #----------------------------------- 
  137. #  decoupage de la chaine en fragment
  138. #  de faτon a isoler le nom du fichier
  139. #  du repertoire
  140. # ---
  141. # split string in fragments to isolate
  142. # the file name from the path name
  143. #----------------------------------- 
  144.  
  145. if DIRNAME.find(os.sep):
  146.     k0=DIRNAME.split(os.sep)
  147. else:
  148.     k0=DIRNAME.split('/')   
  149. DIRNAME=DIRNAME.replace(k0[-1],'')
  150. #----------------------------------- 
  151. # Last release : 0.2.5 ,  2005/05/22 , end
  152. #----------------------------------- 
  153.  
  154. #----------------------------------- 
  155. # Last release : 0.2.4 ,  2005/05/22 , 15h00
  156. #----------------------------------- 
  157. FRAME = Blender.Get('endframe')
  158. #----------------------------------- 
  159. # Last release : 0.2.4 ,  2005/05/22 , end
  160. #----------------------------------- 
  161.  
  162. #----------------------------------- 
  163. # Last release : 0.2.4 ,  2005/05/18 , 11h00
  164. #
  165. # Si  LIMIT == 0 le script n'essaye pas de realiser
  166. # un nouveau cadrage pour que l'image presente toute les
  167. # coordonnΘes uv.
  168. # ---
  169. # if  LIMIT == 0 the script do not try to make
  170. # a new framing with all the uvcoord  in only one
  171. # shoot...
  172. #-----------------------------------
  173. LIMIT=0
  174. #----------------------------------- 
  175. # Last release : 0.2.4 ,  2005/05/18 , END
  176. #----------------------------------- 
  177.  
  178. XYLIMIT = [0.0, 0.0,1.0,1.0]    
  179. OBJPOS = 100.0
  180. DEBUG=1
  181.  
  182. helpmsg = """
  183. Texture Baker:
  184.  
  185. This script saves an uv texture layout of the chosen mesh, that can be used as
  186. an uv map for it.  It is a way to export procedural textures from Blender as
  187. normal image textures that can be edited with a 2d image manipulation program
  188. or used with the mesh in games and other 3d applications.
  189.  
  190. Basic instructions:
  191. - Enter face mode and define uv coordinates for your mesh (do not forget to
  192.   choose a development shape);
  193. - Define its materials and textures ;
  194. - Run this script and check the console.
  195.  
  196. """
  197.  
  198. def GET_newobject (TYPE,NAME):
  199.    """
  200. # ---------------------------
  201. # Function  GET_newobject 
  202. #  IN : TYPE   string , object type ('Mesh','Empty',...)
  203. #       NAME   string , name object  
  204. #  OUT: OBJECT  Blender objetc described in teh string TYPE
  205. #       SCENE   Blender current scene object
  206. # ---------------------------   
  207.     Return and object and the current scene
  208.    """
  209.    SCENE = Blender.Scene.getCurrent()
  210.    OBJECT = Blender.Object.New(TYPE,NAME)
  211.    SCENE.link(OBJECT)
  212.    return OBJECT, SCENE
  213.  
  214. def RenameImage(RDIR, MYDIR, FILENAME, name):
  215.     """
  216. # ---------------------------
  217. # Function  RenameImage
  218. #
  219. #  IN : RDIR      string , current render directory
  220. #       MYDIR     string , new render dir for this shoot
  221. #       FILENAME  string , last rendered image filename 
  222. #       name      string , new name for this image 
  223. #  OUT:  nothing
  224. # ---------------------------
  225.      Rename the file pointed by the string name
  226.      recall the  function if the file yet exists
  227.     """
  228.     newfname = RDIR + MYDIR + name
  229.     if newfname.find('.png', -4) < 0 : newfname += '.png'
  230.     if not Blender.sys.exists(newfname):
  231.        os.rename(FILENAME, newfname)
  232.     else:
  233.         name = Draw.PupStrInput ('ReName Image, please :', name, 32)
  234.         RenameImage(RDIR, MYDIR, FILENAME, name)
  235.  
  236. def SAVE_image (rc, name, FRAME):
  237.    """  
  238. # ---------------------------
  239. # Function  SAVE_image
  240. #
  241. #  IN : rc    current render context object
  242. #       name  string , image name
  243. #       FRAME  integer, last numbre of the curent animation  
  244. #  OUT: nothing  
  245. # ---------------------------   
  246.    """
  247.    rc.enableExtensions(1)   
  248.    MYDIR = ''
  249.    RENDERDIR = rc.getRenderPath().replace('\\','/')
  250.    if RENDERDIR.find('//')==0 : 
  251.       print 'filename', Blender.Get('filename'),'/n', Blender.sys.dirname(Blender.Get('filename')) 
  252.       RDIR=RENDERDIR.replace('//',DIRNAME)
  253.    else:
  254.         RDIR=RENDERDIR[:]
  255.    if DEBUG : print  'RDIR : ', RDIR
  256.     
  257.    HOMEDIR=Blender.Get('homedir')
  258.    if DEBUG : print  'HOMEDIR', HOMEDIR
  259.    rc.setRenderPath(RENDERDIR + MYDIR)
  260.    if DEBUG : print "Render folder:", RENDERDIR + MYDIR
  261.    IMAGETYPE = Blender.Scene.Render.PNG
  262.    if DEBUG : print  'IMAGETYPE : ',IMAGETYPE
  263.    rc.setImageType(IMAGETYPE)
  264.    NEWFRAME = FRAME
  265.    OLDEFRAME = rc.endFrame()
  266.    OLDSFRAME = rc.startFrame()
  267.    rc.startFrame(NEWFRAME)
  268.    rc.endFrame(NEWFRAME)
  269.    rc.renderAnim()
  270.    Blender.Scene.Render.CloseRenderWindow()
  271.  
  272.    FILENAME = "%04d" % NEWFRAME
  273.    FILENAME = FILENAME.replace (' ', '0')
  274.    FILENAME = RDIR + MYDIR + FILENAME + '.png'
  275.  
  276.    RenameImage(RDIR, MYDIR, FILENAME, name)
  277.  
  278.    rc.endFrame(OLDEFRAME)
  279.    rc.startFrame(OLDSFRAME)
  280.    rc.setRenderPath(RENDERDIR)
  281.  
  282. def SHOOT (XYlimit, frame, obj, name, FRAME):
  283.    """
  284. # ---------------------------
  285. # Function  SHOOT
  286. #
  287. #  IN : XYlimit  list of 4 floats, smallest and biggest 
  288. #                uvcoords
  289. #       frame    cureente frame
  290. #       obj      for object location
  291. #       name     image name
  292. #       FRAME    the last animation's frame 
  293. #  OUT:  nothing 
  294. # ---------------------------   
  295.       render and save the baked textures picture 
  296.    """
  297.    try:
  298.       CAM = Blender.Object.Get('UVCAMERA')
  299.       Cam = CAM.getData()
  300.       SC = Blender.Scene.getCurrent()
  301.    except:
  302.       Cam = Blender.Camera.New()
  303.       Cam.name = 'UVCamera'
  304.       CAM, SC = GET_newobject('Camera','UVCAMERA')
  305.       CAM.link(Cam)
  306.       CAM.setName('UVCAMERA')
  307.       Cam.lens = 30
  308.       Cam.name = 'UVCamera'
  309.  
  310.    Cam.setType('ortho')
  311.    Cam.setScale(1.0)
  312.  
  313.    CAM.setLocation(obj.getLocation())
  314.    CAM.LocX += XYlimit[2] * 0.500
  315.    CAM.LocY += XYlimit[3] * 0.500
  316.    CAM.LocZ += max (XYlimit[2], XYlimit[3])
  317.    CAM.setEuler (0.0, 0.0, 0.0)
  318.  
  319.    context = SC.getRenderingContext()
  320.    Camold = SC.getCurrentCamera()
  321.    SC.setCurrentCamera(CAM)
  322.  
  323.    OLDy = context.imageSizeY()
  324.    OLDx = context.imageSizeX()
  325.  
  326.    tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4 | 2048 %x5 ')
  327.  
  328.    if (tres) == 1: res = 256
  329.    elif (tres) == 2: res = 512
  330.    elif (tres) == 3: res = 768
  331.    elif (tres) == 4: res = 1024
  332.    elif (tres) == 5: res = 2048
  333.    else: res = 512
  334.  
  335.    context.imageSizeY(res)
  336.    context.imageSizeX(res)
  337.    SAVE_image (context, name, FRAME)
  338.    context.imageSizeY(OLDy)
  339.    context.imageSizeX(OLDx)
  340.  
  341.    if Camold :SC.setCurrentCamera(Camold)
  342.  
  343.    Blender.Set ('curframe', frame)
  344.  
  345.  
  346. #----------------------------------- 
  347. # release : 0.2.6 ,  2005/05/29 , 00h00
  348. #----------------------------------- 
  349. def PROV_Shadeless(MATList):
  350.     """
  351. # ---------------------------
  352. # Function  PROV_Shadeless
  353. #
  354. #  IN : MATList  a list of the mesh's materials
  355. #  OUT: SHADEDict  a dictionnary  of the materials' shadeles value
  356. # ---------------------------   
  357.     """
  358.     SHADEDict={}
  359.     for mat in MATList:
  360.        SHADEDict[mat.name]=mat.mode
  361.        mat.mode |= Blender.Material.Modes.SHADELESS
  362.     return SHADEDict
  363. #----------------------------------- 
  364. # Last release : 0.2.6 ,  2005/05/29 , end
  365. #----------------------------------- 
  366.  
  367. #----------------------------------- 
  368. # release : 0.2.6 ,  2005/05/29 , 00h00
  369. #----------------------------------- 
  370. def REST_Shadeless(SHADEDict):
  371.     """
  372. # ---------------------------
  373. # Function  REST_Shadeless
  374. #
  375. #  IN : SHADEDict   a dictionnary  of the materials' shadeles value
  376. #  OUT : nothing
  377. # ---------------------------   
  378.     """
  379.     for m in SHADEDict.keys():
  380.        mat=Blender.Material.Get(m)
  381.        mat.mode=SHADEDict[m]
  382. #----------------------------------- 
  383. # release : 0.2.6 ,  2005/05/29 , end
  384. #----------------------------------- 
  385.  
  386. def Mesh2UVCoord (LIMIT):
  387.    """
  388. # ---------------------------
  389. # Function  Mesh2UVCoord
  390. #
  391. #  IN : LIMIT  integer, create or not a new framing for uvcoords 
  392. #  OUT:  nothing
  393. # ---------------------------   
  394.    """
  395.    try:
  396.       MESH3D = Object.GetSelected()[0]
  397.       if MESH3D.getType() == 'Mesh':
  398.          MESH = MESH3D.getData()
  399.  
  400.          try:
  401.             NewOBJECT=Blender.Object.Get('UVOBJECT')
  402.             CurSCENE=Blender.Scene.getCurrent()            
  403.             MESH2 = NewOBJECT.getData()
  404.             
  405.          except:
  406.             NewOBJECT, CurSCENE = GET_newobject('Mesh','UVOBJECT')
  407.             MESH2 = Blender.NMesh.GetRaw()
  408.  
  409.          MESH2.faces=[]
  410.          for f in MESH.faces:
  411.             f1 = Blender.NMesh.Face()
  412.  
  413.             for v in f.v:
  414.                v1 = Blender.NMesh.Vert (v.co[0], v.co[1], v.co[2])
  415.                MESH2.verts.append(v1)
  416.                f1.v.append(MESH2.verts[len(MESH2.verts) - 1])
  417.  
  418.             MESH2.faces.append(f1)
  419.             f1.uv = f.uv[:]
  420.             f1.col = f.col[:]
  421.             f1.smooth = f.smooth
  422.             f1.mode = f.mode
  423.             f1.flag = f.flag
  424.             f1.mat = f.mat
  425.  
  426.          MESH2.materials = MESH.materials[:]
  427.  
  428.          NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
  429.          NewOBJECT.setEuler (0.0, 0.0, 0.0)
  430.  
  431.          MESH2.removeAllKeys()
  432.  
  433.          MESH2.update()
  434.          MESH2.insertKey (1, 'absolute')
  435.          MESH2.update()
  436.  
  437.          for f in MESH2.faces:
  438.             for v in f.v:
  439.                for n in [0,1]:
  440.                   v.co[n] = f.uv[f.v.index(v)][n]
  441.                   exec "if v.co[%s] > XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n+2, n+2, n)
  442.                   exec "if v.co[%s] < XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n, n, n)
  443.                v.co[2] = 0.0
  444.  
  445.          if DEBUG: print XYLIMIT
  446.  
  447.          MESH2.update()
  448.          MESH2.insertKey (FRAME, 'absolute')
  449.          MESH2.update()
  450.  
  451.          imagename = 'uvtext'
  452.  
  453.          name = "CHANGE IMAGE NAME ? %t | Replace it | No replacing | Script help"
  454.          result = Draw.PupMenu(name)
  455.  
  456.          if result == 1:
  457.             imagename = Draw.PupStrInput ('Image Name:', imagename, 32)
  458.  
  459.          if result != 3:
  460.             #----------------------------------- 
  461.             # release : 0.2.6 ,  2005/05/29 , 00h00
  462.             #----------------------------------- 
  463.             SHADEDict=PROV_Shadeless(MESH2.materials)
  464.             #----------------------------------- 
  465.             # release : 0.2.6 ,  2005/05/29 , end
  466.             #----------------------------------- 
  467.  
  468.             if LIMIT :
  469.                  SHOOT(XYLIMIT, FRAME, NewOBJECT, imagename, FRAME)
  470.             else :
  471.                  SHOOT([0.0,0.0,1.0,1.0], FRAME, NewOBJECT, imagename, FRAME)
  472.             #----------------------------------- 
  473.             # release : 0.2.6,  2005/05/29 , 00h00
  474.             #----------------------------------- 
  475.             REST_Shadeless(SHADEDict)
  476.             #----------------------------------- 
  477.             # release : 0.2.6 ,  2005/05/29 , end
  478.             #----------------------------------- 
  479.  
  480.             Blender.Redraw()
  481.  
  482.          else:
  483.             Blender.ShowHelp('tex2uvbaker.py')
  484.             #Draw.PupMenu("Ready%t|Please check console for instructions")
  485.             if DEBUG: print helpmsg
  486.  
  487.       else:
  488.          name = "ERROR: active object is not a mesh or has no UV coordinates"
  489.          result = Draw.PupMenu(name)
  490.          print 'problem : no object selected or not mesh'
  491.  
  492.    except:
  493.       name = "ERROR: active object is not a mesh or has no UV coordinates"
  494.       result = Draw.PupMenu(name)
  495.       print 'problem : no object selected or not mesh'
  496.  
  497. Mesh2UVCoord(LIMIT)
  498.