3
""" Registration info for Blender menus:
7
Tooltip: 'Procedural to uvmapped texture baker'
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"
17
Texture Baker "bakes" Blender procedural materials (including textures): it saves them as 2d uv-mapped images.
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.
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.
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.
36
This script was based on a suggestion by Martin (Theeth) Poirier.
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.
48
# Released under Blender Artistic Licence
51
# -- Creation of LAMP object is removed and replaced
52
# by the use of the shadeless option in material object
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 .
58
# --'pers' camera was replaced by an 'ortho' one.
61
# -- if a image file with the same name exits the
62
# system returns an error
65
# -- a LIMIT variable is added to unlock the uvcoords
70
# Great thanks for Apollux who sees a lot of these
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
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
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.
95
# if the uv mesh objet exists it used,
96
# no creation of a new one. As the lamp and
99
# This script automaticaly frame and shoot the
100
# new uv mesh . The image file is saved ine the
103
#---------------------------------------------
104
# On user-friendly side :
105
#---------------------------------------------
106
#- Tadje Vobovnik adds the Select Image Size Menu
108
#---------------------------------------------
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
#---------------------------------------------
116
from Blender import NMesh, Draw, Object, Scene, Camera
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
124
# It seems that the Blender.sys.dirname function
125
# poses a problem when the memory is too much encumbered
126
#-----------------------------------
135
DIRNAME=Blender.Get('filename')
136
#-----------------------------------
137
# decoupage de la chaine en fragment
138
# de fa�on a isoler le nom du fichier
141
# split string in fragments to isolate
142
# the file name from the path name
143
#-----------------------------------
145
if DIRNAME.find(os.sep):
146
k0=DIRNAME.split(os.sep)
148
k0=DIRNAME.split('/')
149
DIRNAME=DIRNAME.replace(k0[-1],'')
150
#-----------------------------------
151
# Last release : 0.2.5 , 2005/05/22 , end
152
#-----------------------------------
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
#-----------------------------------
162
#-----------------------------------
163
# Last release : 0.2.4 , 2005/05/18 , 11h00
165
# Si LIMIT == 0 le script n'essaye pas de realiser
166
# un nouveau cadrage pour que l'image presente toute les
169
# if LIMIT == 0 the script do not try to make
170
# a new framing with all the uvcoord in only one
172
#-----------------------------------
174
#-----------------------------------
175
# Last release : 0.2.4 , 2005/05/18 , END
176
#-----------------------------------
178
XYLIMIT = [0.0, 0.0,1.0,1.0]
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.
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.
198
def GET_newobject (TYPE,NAME):
200
# ---------------------------
201
# Function GET_newobject
203
# IN : TYPE string , object type ('Mesh','Empty',...)
204
# NAME string , name object
205
# OUT: OBJECT Blender objetc described in teh string TYPE
206
# SCENE Blender current scene object
207
# ---------------------------
208
Return and object and the current scene
210
SCENE = Blender.Scene.getCurrent()
211
OBJECT = Blender.Object.New(TYPE,NAME)
215
def RenameImage(RDIR, MYDIR, FILENAME, name):
217
# ---------------------------
218
# Function RenameImage
220
# IN : RDIR string , current render directory
221
# MYDIR string , new render dir for this shoot
222
# FILENAME string , last rendered image filename
223
# name string , new name for this image
225
# ---------------------------
226
Rename the file pointed by the string name
227
recall the function if the file yet exists
229
newfname = RDIR + MYDIR + name
230
if newfname.find('.png', -4) < 0 : newfname += '.png'
231
if not Blender.sys.exists(newfname):
232
os.rename(FILENAME, newfname)
234
name = Draw.PupStrInput ('ReName Image, please :', name, 32)
235
RenameImage(RDIR, MYDIR, FILENAME, name)
237
def SAVE_image (rc, name, FRAME):
239
# ---------------------------
240
# Function SAVE_image
242
# IN : rc current render context object
243
# name string , image name
244
# FRAME integer, last numbre of the curent animation
246
# ---------------------------
248
rc.enableExtensions(1)
250
RENDERDIR = rc.getRenderPath().replace('\\','/')
251
if RENDERDIR.find('//')==0 :
252
print 'filename', Blender.Get('filename'),'/n', Blender.sys.dirname(Blender.Get('filename'))
253
RDIR=RENDERDIR.replace('//',DIRNAME)
256
if DEBUG : print 'RDIR : ', RDIR
258
HOMEDIR=Blender.Get('homedir')
259
if DEBUG : print 'HOMEDIR', HOMEDIR
260
rc.setRenderPath(RENDERDIR + MYDIR)
261
if DEBUG : print "Render folder:", RENDERDIR + MYDIR
262
IMAGETYPE = Blender.Scene.Render.PNG
263
if DEBUG : print 'IMAGETYPE : ',IMAGETYPE
264
rc.setImageType(IMAGETYPE)
266
OLDEFRAME = rc.endFrame()
267
OLDSFRAME = rc.startFrame()
268
rc.startFrame(NEWFRAME)
269
rc.endFrame(NEWFRAME)
271
Blender.Scene.Render.CloseRenderWindow()
273
FILENAME = "%04d" % NEWFRAME
274
FILENAME = FILENAME.replace (' ', '0')
275
FILENAME = RDIR + MYDIR + FILENAME + '.png'
277
RenameImage(RDIR, MYDIR, FILENAME, name)
279
rc.endFrame(OLDEFRAME)
280
rc.startFrame(OLDSFRAME)
281
rc.setRenderPath(RENDERDIR)
283
def SHOOT (XYlimit, frame, obj, name, FRAME):
285
# ---------------------------
288
# IN : XYlimit list of 4 floats, smallest and biggest
290
# frame cureente frame
291
# obj for object location
293
# FRAME the last animation's frame
295
# ---------------------------
296
render and save the baked textures picture
299
CAM = Blender.Object.Get('UVCAMERA')
301
SC = Blender.Scene.getCurrent()
303
Cam = Blender.Camera.New()
304
Cam.name = 'UVCamera'
305
CAM, SC = GET_newobject('Camera','UVCAMERA')
307
CAM.setName('UVCAMERA')
309
Cam.name = 'UVCamera'
314
CAM.setLocation(obj.getLocation())
315
CAM.LocX += XYlimit[2] * 0.500
316
CAM.LocY += XYlimit[3] * 0.500
317
CAM.LocZ += max (XYlimit[2], XYlimit[3])
318
CAM.setEuler (0.0, 0.0, 0.0)
320
context = SC.getRenderingContext()
321
Camold = SC.getCurrentCamera()
322
SC.setCurrentCamera(CAM)
324
OLDy = context.imageSizeY()
325
OLDx = context.imageSizeX()
327
tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4 | 2048 %x5 ')
329
if (tres) == 1: res = 256
330
elif (tres) == 2: res = 512
331
elif (tres) == 3: res = 768
332
elif (tres) == 4: res = 1024
333
elif (tres) == 5: res = 2048
336
context.imageSizeY(res)
337
context.imageSizeX(res)
338
SAVE_image (context, name, FRAME)
339
context.imageSizeY(OLDy)
340
context.imageSizeX(OLDx)
342
if Camold :SC.setCurrentCamera(Camold)
344
Blender.Set ('curframe', frame)
347
#-----------------------------------
348
# release : 0.2.6 , 2005/05/29 , 00h00
349
#-----------------------------------
350
def PROV_Shadeless(MATList):
352
# ---------------------------
353
# Function PROV_Shadeless
355
# IN : MATList a list of the mesh's materials
356
# OUT: SHADEDict a dictionnary of the materials' shadeles value
357
# ---------------------------
361
SHADEDict[mat.name]=mat.mode
362
mat.mode |= Blender.Material.Modes.SHADELESS
364
#-----------------------------------
365
# Last release : 0.2.6 , 2005/05/29 , end
366
#-----------------------------------
368
#-----------------------------------
369
# release : 0.2.6 , 2005/05/29 , 00h00
370
#-----------------------------------
371
def REST_Shadeless(SHADEDict):
373
# ---------------------------
374
# Function REST_Shadeless
376
# IN : SHADEDict a dictionnary of the materials' shadeles value
378
# ---------------------------
380
for m in SHADEDict.keys():
381
mat=Blender.Material.Get(m)
382
mat.mode=SHADEDict[m]
383
#-----------------------------------
384
# release : 0.2.6 , 2005/05/29 , end
385
#-----------------------------------
387
def Mesh2UVCoord (LIMIT):
389
# ---------------------------
390
# Function Mesh2UVCoord
392
# IN : LIMIT integer, create or not a new framing for uvcoords
394
# ---------------------------
397
MESH3D = Object.GetSelected()[0]
398
if MESH3D.getType() == 'Mesh':
399
MESH = MESH3D.getData()
402
NewOBJECT=Blender.Object.Get('UVOBJECT')
403
CurSCENE=Blender.Scene.getCurrent()
404
MESH2 = NewOBJECT.getData()
407
NewOBJECT, CurSCENE = GET_newobject('Mesh','UVOBJECT')
408
MESH2 = Blender.NMesh.GetRaw()
412
f1 = Blender.NMesh.Face()
415
v1 = Blender.NMesh.Vert (v.co[0], v.co[1], v.co[2])
416
MESH2.verts.append(v1)
417
f1.v.append(MESH2.verts[len(MESH2.verts) - 1])
419
MESH2.faces.append(f1)
427
MESH2.materials = MESH.materials[:]
429
NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
430
NewOBJECT.setEuler (0.0, 0.0, 0.0)
432
MESH2.removeAllKeys()
435
MESH2.insertKey (1, 'absolute')
438
for f in MESH2.faces:
441
v.co[n] = f.uv[f.v.index(v)][n]
442
exec "if v.co[%s] > XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n+2, n+2, n)
443
exec "if v.co[%s] < XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n, n, n)
446
if DEBUG: print XYLIMIT
449
MESH2.insertKey (FRAME, 'absolute')
454
name = "CHANGE IMAGE NAME ? %t | Replace it | No replacing | Script help"
455
result = Draw.PupMenu(name)
458
imagename = Draw.PupStrInput ('Image Name:', imagename, 32)
461
#-----------------------------------
462
# release : 0.2.6 , 2005/05/29 , 00h00
463
#-----------------------------------
464
SHADEDict=PROV_Shadeless(MESH2.materials)
465
#-----------------------------------
466
# release : 0.2.6 , 2005/05/29 , end
467
#-----------------------------------
470
SHOOT(XYLIMIT, FRAME, NewOBJECT, imagename, FRAME)
472
SHOOT([0.0,0.0,1.0,1.0], FRAME, NewOBJECT, imagename, FRAME)
473
#-----------------------------------
474
# release : 0.2.6, 2005/05/29 , 00h00
475
#-----------------------------------
476
REST_Shadeless(SHADEDict)
477
#-----------------------------------
478
# release : 0.2.6 , 2005/05/29 , end
479
#-----------------------------------
484
Blender.ShowHelp('tex2uvbaker.py')
485
#Draw.PupMenu("Ready%t|Please check console for instructions")
486
if DEBUG: print helpmsg
489
name = "ERROR: active object is not a mesh or has no UV coordinates"
490
result = Draw.PupMenu(name)
491
print 'problem : no object selected or not mesh'
494
name = "ERROR: active object is not a mesh or has no UV coordinates"
495
result = Draw.PupMenu(name)
496
print 'problem : no object selected or not mesh'