Newer
Older
Bastien Montagne
committed
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# #**** END GPL LICENSE BLOCK #****
import subprocess
import os
import sys
import time
import re
import platform#
import subprocess#
from bpy.types import(Operator)#all added for render preview
##############################SF###########################
##############find image texture
ext = {
'JPG': "jpeg",
'JPEG': "jpeg",
'GIF': "gif",
'TGA': "tga",
'IFF': "iff",
'PPM': "ppm",
'PNG': "png",
'SYS': "sys",
'TIFF': "tiff",
'TIF': "tiff",
'EXR': "exr",
'HDR': "hdr",
}.get(os.path.splitext(imgF)[-1].upper(), "")
print(" WARNING: texture image format not supported ")
image_map = ""
if ts.mapping == 'FLAT':
image_map = "map_type 0 "
elif ts.mapping == 'SPHERE':
image_map = "map_type 1 "
elif ts.mapping == 'TUBE':
image_map = "map_type 2 "
## map_type 3 and 4 in development (?)
## for POV-Ray, currently they just seem to default back to Flat (type 0)
#elif ts.mapping=="?":
#elif ts.mapping=="?":
if ts.texture.use_interpolation:
image_map += " interpolate 2 "
if ts.texture.extension == 'CLIP':
image_map += " once "
#image_map += "}"
#if ts.mapping=='CUBE':
# image_map+= "warp { cubic } rotate <-90,0,180>"
# no direct cube type mapping. Though this should work in POV 3.7
# it doesn't give that good results(best suited to environment maps?)
# print(" No texture image found ")
# texture_coords refers to the mapping of world textures:
if wts.texture_coords == 'VIEW':
elif wts.texture_coords == 'ANGMAP':
image_mapBG = " map_type 1 "
elif wts.texture_coords == 'TUBE':
image_mapBG = " map_type 2 "
if wts.texture.use_interpolation:
image_mapBG += " interpolate 2 "
if wts.texture.extension == 'CLIP':
image_mapBG += " once "
#image_mapBG += "}"
#if wts.mapping == 'CUBE':
# image_mapBG += "warp { cubic } rotate <-90,0,180>"
# no direct cube type mapping. Though this should work in POV 3.7
# it doesn't give that good results(best suited to environment maps?)
#if image_mapBG == "":
# print(" No background texture image found ")
return bpy.path.abspath(image.filepath, library=image.library)
# end find image texture
# -----------------------------------------------------------------------------
def string_strip_hyphen(name):
return name.replace("-", "")
def safety(name, Level):
# safety string name material
#
# Level=1 is for texture with No specular nor Mirror reflection
# Level=2 is for texture with translation of spec and mir levels
# for when no map influences them
# Level=3 is for texture with Maximum Spec and Mirror
Maurice Raybaud
committed
prefix = ""
return prefix + name + "0" # used for 0 of specular map
return prefix + name + "1" # used for 1 of specular map
Maurice Raybaud
committed
##############end safety string name material
##############################EndSF###########################
def is_renderable(ob):
return (ob.hide_render==False)
def renderable_objects():
return [ob for ob in bpy.data.objects if is_renderable(ob)]
Maurice Raybaud
committed
tabLevel = 0
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
unpacked_images=[]
def exportPattern(texture):
tex=texture
pat = tex.pov
PATname = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(tex.name))
mappingDif = ("translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % \
(pat.tex_mov_x, pat.tex_mov_y, pat.tex_mov_z,
1.0 / pat.tex_scale_x, 1.0 / pat.tex_scale_y, 1.0 / pat.tex_scale_z))
texStrg=""
def exportColorRamp(texture):
tex=texture
pat = tex.pov
colRampStrg="color_map {\n"
numColor=0
for el in tex.color_ramp.elements:
numColor+=1
pos = el.position
col=el.color
colR,colG,colB,colA = col[0],col[1],col[2],1-col[3]
if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} :
colRampStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA)
if pat.tex_pattern_type in {'brick','checker'} and numColor < 3:
colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'hexagon' and numColor < 4 :
colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'square' and numColor < 5 :
colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'triangular' and numColor < 7 :
colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
colRampStrg+="} \n"
#end color map
return colRampStrg
#much work to be done here only defaults translated for now:
#pov noise_generator 3 means perlin noise
if pat.tex_pattern_type == 'emulator':
texStrg+="pigment {\n"
####################### EMULATE BLENDER VORONOI TEXTURE ####################
if tex.type == 'VORONOI':
texStrg+="crackle\n"
texStrg+=" offset %.4g\n"%tex.nabla
texStrg+=" form <%.4g,%.4g,%.4g>\n"%(tex.weight_1, tex.weight_2, tex.weight_3)
if tex.distance_metric == 'DISTANCE':
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
texStrg+=" metric 2.5\n"
if tex.distance_metric == 'DISTANCE_SQUARED':
texStrg+=" metric 2.5\n"
texStrg+=" poly_wave 2\n"
if tex.distance_metric == 'MINKOVSKY':
texStrg+=" metric %s\n"%tex.minkovsky_exponent
if tex.distance_metric == 'MINKOVSKY_FOUR':
texStrg+=" metric 4\n"
if tex.distance_metric == 'MINKOVSKY_HALF':
texStrg+=" metric 0.5\n"
if tex.distance_metric == 'CHEBYCHEV':
texStrg+=" metric 10\n"
if tex.distance_metric == 'MANHATTAN':
texStrg+=" metric 1\n"
if tex.color_mode == 'POSITION':
texStrg+="solid\n"
texStrg+="scale 0.25\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<0,0,0,1>]\n"
texStrg+="[1 color rgbt<1,1,1,0>]\n"
texStrg+="}\n"
####################### EMULATE BLENDER CLOUDS TEXTURE ####################
if tex.type == 'CLOUDS':
if tex.noise_type == 'SOFT_NOISE':
texStrg+="wrinkles\n"
texStrg+="scale 0.25\n"
else:
texStrg+="granite\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<0,0,0,1>]\n"
texStrg+="[1 color rgbt<1,1,1,0>]\n"
texStrg+="}\n"
####################### EMULATE BLENDER WOOD TEXTURE ####################
if tex.type == 'WOOD':
if tex.wood_type == 'RINGS':
texStrg+="wood\n"
texStrg+="scale 0.25\n"
if tex.wood_type == 'RINGNOISE':
texStrg+="wood\n"
texStrg+="scale 0.25\n"
texStrg+="turbulence %.4g\n"%(tex.turbulence/100)
if tex.wood_type == 'BANDS':
texStrg+="marble\n"
texStrg+="scale 0.25\n"
texStrg+="rotate <45,-45,45>\n"
if tex.wood_type == 'BANDNOISE':
texStrg+="marble\n"
texStrg+="scale 0.25\n"
texStrg+="rotate <45,-45,45>\n"
texStrg+="turbulence %.4g\n"%(tex.turbulence/10)
if tex.noise_basis_2 == 'SIN':
texStrg+="sine_wave\n"
if tex.noise_basis_2 == 'TRI':
texStrg+="triangle_wave\n"
if tex.noise_basis_2 == 'SAW':
texStrg+="ramp_wave\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<0,0,0,0>]\n"
texStrg+="[1 color rgbt<1,1,1,0>]\n"
texStrg+="}\n"
####################### EMULATE BLENDER STUCCI TEXTURE ####################
if tex.type == 'STUCCI':
texStrg+="bozo\n"
texStrg+="scale 0.25\n"
if tex.noise_type == 'HARD_NOISE':
texStrg+="triangle_wave\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbf<1,1,1,0>]\n"
texStrg+="[1 color rgbt<0,0,0,1>]\n"
texStrg+="}\n"
else:
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbf<0,0,0,1>]\n"
texStrg+="[1 color rgbt<1,1,1,0>]\n"
texStrg+="}\n"
####################### EMULATE BLENDER MAGIC TEXTURE ####################
if tex.type == 'MAGIC':
texStrg+="leopard\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0.5>]\n"
texStrg+="[0.25 color rgbf<0,1,0,0.75>]\n"
texStrg+="[0.5 color rgbf<0,0,1,0.75>]\n"
texStrg+="[0.75 color rgbf<1,0,1,0.75>]\n"
texStrg+="[1 color rgbf<0,1,0,0.75>]\n"
texStrg+="}\n"
texStrg+="scale 0.1\n"
####################### EMULATE BLENDER MARBLE TEXTURE ####################
if tex.type == 'MARBLE':
texStrg+="marble\n"
texStrg+="turbulence 0.5\n"
texStrg+="noise_generator 3\n"
texStrg+="scale 0.75\n"
texStrg+="rotate <45,-45,45>\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
if tex.marble_type == 'SOFT':
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<0,0,0,0>]\n"
texStrg+="[0.05 color rgbt<0,0,0,0>]\n"
texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n"
texStrg+="}\n"
elif tex.marble_type == 'SHARP':
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<0,0,0,0>]\n"
texStrg+="[0.025 color rgbt<0,0,0,0>]\n"
texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n"
texStrg+="}\n"
else:
texStrg+="[0 color rgbt<0,0,0,0>]\n"
texStrg+="[1 color rgbt<1,1,1,0>]\n"
texStrg+="}\n"
if tex.noise_basis_2 == 'SIN':
texStrg+="sine_wave\n"
if tex.noise_basis_2 == 'TRI':
texStrg+="triangle_wave\n"
if tex.noise_basis_2 == 'SAW':
texStrg+="ramp_wave\n"
####################### EMULATE BLENDER BLEND TEXTURE ####################
if tex.type == 'BLEND':
if tex.progression=='RADIAL':
texStrg+="radial\n"
if tex.use_flip_axis=='HORIZONTAL':
texStrg+="rotate x*90\n"
else:
texStrg+="rotate <-90,0,90>\n"
texStrg+="ramp_wave\n"
elif tex.progression=='SPHERICAL':
texStrg+="spherical\n"
texStrg+="scale 3\n"
texStrg+="poly_wave 1\n"
elif tex.progression=='QUADRATIC_SPHERE':
texStrg+="spherical\n"
texStrg+="scale 3\n"
texStrg+=" poly_wave 2\n"
elif tex.progression=='DIAGONAL':
texStrg+="gradient <1,1,0>\n"
texStrg+="scale 3\n"
elif tex.use_flip_axis=='HORIZONTAL':
texStrg+="gradient x\n"
texStrg+="scale 2.01\n"
elif tex.use_flip_axis=='VERTICAL':
texStrg+="gradient y\n"
texStrg+="scale 2.01\n"
#texStrg+="ramp_wave\n"
#texStrg+="frequency 0.5\n"
texStrg+="phase 0.5\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
if tex.progression == 'LINEAR':
texStrg+=" poly_wave 1\n"
if tex.progression == 'QUADRATIC':
texStrg+=" poly_wave 2\n"
if tex.progression == 'EASING':
texStrg+=" poly_wave 1.5\n"
####################### EMULATE BLENDER MUSGRAVE TEXTURE ####################
# if tex.type == 'MUSGRAVE':
# texStrg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n"
# texStrg+="color_map {\n"
# texStrg+="[0 color rgbf<0,0,0,1>]\n"
# texStrg+="[1 color rgbf<1,1,1,0>]\n"
# texStrg+="}\n"
# simplified for now:
if tex.type == 'MUSGRAVE':
texStrg+="bozo scale 0.25 \n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n"
####################### EMULATE BLENDER DISTORTED NOISE TEXTURE ####################
if tex.type == 'DISTORTED_NOISE':
texStrg+="average\n"
texStrg+=" pigment_map {\n"
texStrg+=" [1 bozo scale 0.25 turbulence %.4g\n" %tex.distortion
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
texStrg+="]\n"
if tex.noise_distortion == 'CELL_NOISE':
texStrg+=" [1 cells scale 0.1\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
texStrg+="]\n"
if tex.noise_distortion=='VORONOI_CRACKLE':
texStrg+=" [1 crackle scale 0.25\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
texStrg+="]\n"
if tex.noise_distortion in ['VORONOI_F1','VORONOI_F2','VORONOI_F3','VORONOI_F4','VORONOI_F2_F1']:
texStrg+=" [1 crackle metric 2.5 scale 0.25 turbulence %.4g\n" %(tex.distortion/2)
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
texStrg+="]\n"
else:
texStrg+=" [1 wrinkles scale 0.25\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0 color rgbt<1,1,1,0>]\n"
texStrg+="[1 color rgbf<0,0,0,1>]\n"
texStrg+="}\n"
texStrg+="]\n"
texStrg+=" }\n"
####################### EMULATE BLENDER NOISE TEXTURE ####################
if tex.type == 'NOISE':
texStrg+="cells\n"
texStrg+="turbulence 3\n"
texStrg+="omega 3\n"
if tex.use_color_ramp == True:
texStrg+=exportColorRamp(tex)
else:
texStrg+="color_map {\n"
texStrg+="[0.75 color rgb<0,0,0,>]\n"
texStrg+="[1 color rgb<1,1,1,>]\n"
texStrg+="}\n"
####################### IGNORE OTHER BLENDER TEXTURE ####################
else: #non translated textures
pass
texStrg+="}\n\n"
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
texStrg+="#declare f%s=\n"%PATname
texStrg+="function{pigment{%s}}\n"%PATname
texStrg+="\n"
else:
texStrg+="pigment {\n"
texStrg+="%s\n"%pat.tex_pattern_type
if pat.tex_pattern_type == 'agate':
texStrg+="agate_turb %.4g\n"%pat.modifier_turbulence
if pat.tex_pattern_type in {'spiral1', 'spiral2', 'tiling'}:
texStrg+="%s\n"%pat.modifier_numbers
if pat.tex_pattern_type == 'quilted':
texStrg+="control0 %s control1 %s\n"%(pat.modifier_control0, pat.modifier_control1)
if pat.tex_pattern_type == 'mandel':
texStrg+="%s exponent %s \n"%(pat.f_iter, pat.f_exponent)
if pat.tex_pattern_type == 'julia':
texStrg+="<%.4g, %.4g> %s exponent %s \n"%(pat.julia_complex_1, pat.julia_complex_2, pat.f_iter, pat.f_exponent)
if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'mandel':
texStrg+="%s mandel %s \n"%(pat.magnet_type, pat.f_iter)
if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'julia':
texStrg+="%s julia <%.4g, %.4g> %s\n"%(pat.magnet_type, pat.julia_complex_1, pat.julia_complex_2, pat.f_iter)
if pat.tex_pattern_type in {'mandel', 'julia', 'magnet'}:
texStrg+="interior %s, %.4g\n"%(pat.f_ior, pat.f_ior_fac)
texStrg+="exterior %s, %.4g\n"%(pat.f_eor, pat.f_eor_fac)
if pat.tex_pattern_type == 'gradient':
texStrg+="<%s, %s, %s> \n"%(pat.grad_orient_x, pat.grad_orient_y, pat.grad_orient_z)
if pat.tex_pattern_type == 'pavement':
numTiles=pat.pave_tiles
numPattern=1
if pat.pave_sides == '4' and pat.pave_tiles == 3:
numPattern = pat.pave_pat_2
if pat.pave_sides == '6' and pat.pave_tiles == 3:
numPattern = pat.pave_pat_3
if pat.pave_sides == '3' and pat.pave_tiles == 4:
numPattern = pat.pave_pat_3
if pat.pave_sides == '3' and pat.pave_tiles == 5:
numPattern = pat.pave_pat_4
if pat.pave_sides == '4' and pat.pave_tiles == 4:
numPattern = pat.pave_pat_5
if pat.pave_sides == '6' and pat.pave_tiles == 4:
numPattern = pat.pave_pat_7
if pat.pave_sides == '4' and pat.pave_tiles == 5:
numPattern = pat.pave_pat_12
if pat.pave_sides == '3' and pat.pave_tiles == 6:
numPattern = pat.pave_pat_12
if pat.pave_sides == '6' and pat.pave_tiles == 5:
numPattern = pat.pave_pat_22
if pat.pave_sides == '4' and pat.pave_tiles == 6:
numPattern = pat.pave_pat_35
if pat.pave_sides == '6' and pat.pave_tiles == 6:
numTiles = 5
texStrg+="number_of_sides %s number_of_tiles %s pattern %s form %s \n"%(pat.pave_sides, numTiles, numPattern, pat.pave_form)
################ functions #####################################################################################################
if pat.tex_pattern_type == 'function':
texStrg+="{ %s"%pat.func_list
texStrg+="(x"
if pat.func_plus_x != "NONE":
if pat.func_plus_x =='increase':
texStrg+="*"
if pat.func_plus_x =='plus':
texStrg+="+"
texStrg+="%.4g"%pat.func_x
texStrg+=",y"
if pat.func_plus_y != "NONE":
if pat.func_plus_y =='increase':
texStrg+="*"
if pat.func_plus_y =='plus':
texStrg+="+"
texStrg+="%.4g"%pat.func_y
texStrg+=",z"
if pat.func_plus_z != "NONE":
if pat.func_plus_z =='increase':
texStrg+="*"
if pat.func_plus_z =='plus':
texStrg+="+"
texStrg+="%.4g"%pat.func_z
sort = -1
if pat.func_list in {"f_comma","f_crossed_trough","f_cubic_saddle","f_cushion","f_devils_curve",
"f_enneper","f_glob","f_heart","f_hex_x","f_hex_y","f_hunt_surface",
"f_klein_bottle","f_kummer_surface_v1","f_lemniscate_of_gerono","f_mitre",
"f_nodal_cubic","f_noise_generator","f_odd","f_paraboloid","f_pillow",
"f_piriform","f_quantum","f_quartic_paraboloid","f_quartic_saddle",
"f_sphere","f_steiners_roman","f_torus_gumdrop","f_umbrella"}:
sort = 0
if pat.func_list in {"f_bicorn","f_bifolia","f_boy_surface","f_superellipsoid","f_torus"}:
sort = 1
if pat.func_list in {"f_ellipsoid","f_folium_surface","f_hyperbolic_torus",
"f_kampyle_of_eudoxus","f_parabolic_torus","f_quartic_cylinder","f_torus2"}:
sort = 2
if pat.func_list in {"f_blob2","f_cross_ellipsoids","f_flange_cover","f_isect_ellipsoids",
"f_kummer_surface_v2","f_ovals_of_cassini","f_rounded_box","f_spikes_2d","f_strophoid"}:
sort = 3
if pat.func_list in {"f_algbr_cyl1","f_algbr_cyl2","f_algbr_cyl3","f_algbr_cyl4","f_blob","f_mesh1","f_poly4","f_spikes"}:
sort = 4
if pat.func_list in {"f_devils_curve_2d","f_dupin_cyclid","f_folium_surface_2d","f_hetero_mf","f_kampyle_of_eudoxus_2d",
"f_lemniscate_of_gerono_2d","f_polytubes","f_ridge","f_ridged_mf","f_spiral","f_witch_of_agnesi"}:
sort = 5
if pat.func_list in {"f_helix1","f_helix2","f_piriform_2d","f_strophoid_2d"}:
sort = 6
if pat.func_list == "f_helical_torus":
sort = 7
if sort > -1:
texStrg+=",%.4g"%pat.func_P0
if sort > 0:
texStrg+=",%.4g"%pat.func_P1
if sort > 1:
texStrg+=",%.4g"%pat.func_P2
if sort > 2:
texStrg+=",%.4g"%pat.func_P3
if sort > 3:
texStrg+=",%.4g"%pat.func_P4
if sort > 4:
texStrg+=",%.4g"%pat.func_P5
if sort > 5:
texStrg+=",%.4g"%pat.func_P6
if sort > 6:
texStrg+=",%.4g"%pat.func_P7
texStrg+=",%.4g"%pat.func_P8
texStrg+=",%.4g"%pat.func_P9
texStrg+=")}\n"
############## end functions ###############################################################
if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}:
texStrg+="color_map {\n"
numColor=0
if tex.use_color_ramp == True:
for el in tex.color_ramp.elements:
numColor+=1
pos = el.position
col=el.color
colR,colG,colB,colA = col[0],col[1],col[2],1-col[3]
if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} :
texStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA)
if pat.tex_pattern_type in {'brick','checker'} and numColor < 3:
texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'hexagon' and numColor < 4 :
texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'square' and numColor < 5 :
texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
if pat.tex_pattern_type == 'triangular' and numColor < 7 :
texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA)
else:
texStrg+="[0 color rgbf<0,0,0,1>]\n"
texStrg+="[1 color rgbf<1,1,1,0>]\n"
if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} :
texStrg+="} \n"
if pat.tex_pattern_type == 'brick':
texStrg+="brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(pat.brick_size_x, pat.brick_size_y, pat.brick_size_z, pat.brick_mortar)
texStrg+="%s \n"%mappingDif
texStrg+="rotate <%.4g,%.4g,%.4g> \n"%(pat.tex_rot_x, pat.tex_rot_y, pat.tex_rot_z)
texStrg+="turbulence <%.4g,%.4g,%.4g> \n"%(pat.warp_turbulence_x, pat.warp_turbulence_y, pat.warp_turbulence_z)
texStrg+="octaves %s \n"%pat.modifier_octaves
texStrg+="lambda %.4g \n"%pat.modifier_lambda
texStrg+="omega %.4g \n"%pat.modifier_omega
texStrg+="frequency %.4g \n"%pat.modifier_frequency
texStrg+="phase %.4g \n"%pat.modifier_phase
texStrg+="}\n\n"
texStrg+="#declare f%s=\n"%PATname
texStrg+="function{pigment{%s}}\n"%PATname
texStrg+="\n"
return(texStrg)
Campbell Barton
committed
import mathutils
# Only for testing
if not scene:
scene = bpy.data.scenes[0]
render = scene.render
world = scene.world
global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
comments = scene.pov.comments_enable and not scene.pov.tempfiles_enable
linebreaksinlists= scene.pov.list_lf_enable and not scene.pov.tempfiles_enable
Constantin Rahn
committed
def setTab(tabtype, spaces):
TabStr = ""
Campbell Barton
committed
if tabtype == 'NONE':
TabStr = ""
Campbell Barton
committed
elif tabtype == 'TAB':
TabStr = "\t"
Campbell Barton
committed
elif tabtype == 'SPACE':
TabStr = spaces * " "
Constantin Rahn
committed
return TabStr
Bastien Montagne
committed
tab = setTab(scene.pov.indentation_character, scene.pov.indentation_spaces)
if not scene.pov.tempfiles_enable:
def tabWrite(str_o):
global tabLevel
brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]")
if brackets < 0:
tabLevel = tabLevel + brackets
if tabLevel < 0:
print("Indentation Warning: tabLevel = %s" % tabLevel)
tabLevel = 0
if tabLevel >= 1:
file.write("%s" % tab * tabLevel)
file.write(str_o)
if brackets > 0:
tabLevel = tabLevel + brackets
Constantin Rahn
committed
def uniqueName(name, nameSeq):
if name not in nameSeq:
return name
name_orig = name
i = 1
while name in nameSeq:
name = "%s_%.3d" % (name_orig, i)
tabWrite("matrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n" %
(matrix[0][0], matrix[1][0], matrix[2][0],
matrix[0][1], matrix[1][1], matrix[2][1],
matrix[0][2], matrix[1][2], matrix[2][2],
matrix[0][3], matrix[1][3], matrix[2][3]))
Bastien Montagne
committed
def MatrixAsPovString(matrix):
sMatrix = ("matrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n" %
(matrix[0][0], matrix[1][0], matrix[2][0],
matrix[0][1], matrix[1][1], matrix[2][1],
matrix[0][2], matrix[1][2], matrix[2][2],
matrix[0][3], matrix[1][3], matrix[2][3]))
Bastien Montagne
committed
return sMatrix
def writeObjectMaterial(material, ob):
Doug Hammond
committed
# DH - modified some variables to be function local, avoiding RNA write
# this should be checked to see if it is functionally correct
Bastien Montagne
committed
# Commented out: always write IOR to be able to use it for SSS, Fresnel reflections...
#if material and material.transparency_method == 'RAYTRACE':
if material:
# But there can be only one!
if material.subsurface_scattering.use: # SSS IOR get highest priority
tabWrite("interior {\n")
tabWrite("ior %.6f\n" % material.subsurface_scattering.ior)
Bastien Montagne
committed
# Then the raytrace IOR taken from raytrace transparency properties and used for
# reflections if IOR Mirror option is checked.
elif material.pov.mirror_use_IOR:
tabWrite("interior {\n")
tabWrite("ior %.6f\n" % material.raytrace_transparency.ior)
tabWrite("interior {\n")
tabWrite("ior %.6f\n" % material.raytrace_transparency.ior)
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
pov_photons_reflection = False
Bastien Montagne
committed
if material.pov.photons_reflection:
Bastien Montagne
committed
if material.pov.refraction_type == "0":
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
Bastien Montagne
committed
elif material.pov.refraction_type == "1":
Doug Hammond
committed
pov_fake_caustics = True
pov_photons_refraction = False
Bastien Montagne
committed
elif material.pov.refraction_type == "2":
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = True
Bastien Montagne
committed
# If only Raytrace transparency is set, its IOR will be used for refraction, but user
# can set up 'un-physical' fresnel reflections in raytrace mirror parameters.
# Last, if none of the above is specified, user can set up 'un-physical' fresnel
# reflections in raytrace mirror parameters. And pov IOR defaults to 1.
if material.pov.caustics_enable:
Doug Hammond
committed
if pov_fake_caustics:
Bastien Montagne
committed
tabWrite("caustics %.3g\n" % material.pov.fake_caustics_power)
Maurice Raybaud
committed
if pov_photons_refraction:
Bastien Montagne
committed
# Default of 1 means no dispersion
tabWrite("dispersion %.6f\n" % material.pov.photons_dispersion)
Maurice Raybaud
committed
tabWrite("dispersion_samples %.d\n" % material.pov.photons_dispersion_samples)
if material.use_transparency and material.transparency_method == 'RAYTRACE':
# fade_distance
Bastien Montagne
committed
# In Blender this value has always been reversed compared to what tooltip says.
# 100.001 rather than 100 so that it does not get to 0
# which deactivates the feature in POV
Bastien Montagne
committed
tabWrite("fade_distance %.3g\n" % \
(100.001 - material.raytrace_transparency.depth_max))
# fade_power
tabWrite("fade_power %.3g\n" % material.raytrace_transparency.falloff)
# fade_color
Bastien Montagne
committed
tabWrite("fade_color <%.3g, %.3g, %.3g>\n" % material.pov.interior_fade_color[:])
# (variable) dispersion_samples (constant count for now)
tabWrite("}\n")
if material.pov.photons_reflection or material.pov.refraction_type=="2":
tabWrite("photons{")
Maurice Raybaud
committed
tabWrite("target %.3g\n" % ob.pov.spacing_multiplier)
if not ob.pov.collect_photons:
tabWrite("collect off\n")
if pov_photons_refraction:
tabWrite("refraction on\n")
if pov_photons_reflection:
tabWrite("reflection on\n")
tabWrite("}\n")
DEF_MAT_NAME = "" #or "Default"?
def writeMaterial(material):
# Assumes only called once on each material
if material:
name_orig = material.name
name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames)
name = name_orig = DEF_MAT_NAME
Maurice Raybaud
committed
if material:
# If saturation(.s) is not zero, then color is not grey, and has a tint
colored_specular_found = (material.specular_color.s > 0.0)
Bastien Montagne
committed
##################
# Several versions of the finish: Level conditions are variations for specular/Mirror
# texture channel map with alternative finish of 0 specular and no mirror reflection.
# Level=1 Means No specular nor Mirror reflection
# Level=2 Means translation of spec and mir levels for when no map influences them
# Level=3 Means Maximum Spec and Mirror
def povHasnoSpecularMaps(Level):
tabWrite("#declare %s = finish {" % safety(name, Level=1))
file.write(" //No specular nor Mirror reflection\n")
tabWrite("\n")
tabWrite("#declare %s = finish {" % safety(name, Level=2))
Bastien Montagne
committed
file.write(" //translation of spec and mir levels for when no map " \
"influences them\n")
tabWrite("\n")
tabWrite("#declare %s = finish {" % safety(name, Level=3))
file.write(" //Maximum Spec and Mirror\n")
tabWrite("\n")
Bastien Montagne
committed
# POV-Ray 3.7 now uses two diffuse values respectively for front and back shading
# (the back diffuse is like blender translucency)
frontDiffuse = material.diffuse_intensity
backDiffuse = material.translucency
Bastien Montagne
committed
if material.pov.conserve_energy:
#Total should not go above one
if (frontDiffuse + backDiffuse) <= 1.0:
pass
elif frontDiffuse == backDiffuse:
Bastien Montagne
committed
# Try to respect the user's 'intention' by comparing the two values but
# bringing the total back to one.
frontDiffuse = backDiffuse = 0.5
# Let the highest value stay the highest value.
elif frontDiffuse > backDiffuse:
# clamps the sum below 1
backDiffuse = min(backDiffuse, (1.0 - frontDiffuse))
# map hardness between 0.0 and 1.0
roughness = ((1.0 - ((material.specular_hardness - 1.0) / 510.0)))
## scale from 0.0 to 0.1
Bastien Montagne
committed
# add a small value because 0.0 is invalid.
Bastien Montagne
committed
################################Diffuse Shader######################################
# Not used for Full spec (Level=3) of the shader.
if material.diffuse_shader == 'OREN_NAYAR' and Level != 3:
Bastien Montagne
committed
# Blender roughness is what is generally called oren nayar Sigma,
# and brilliance in POV-Ray.
tabWrite("brilliance %.3g\n" % (0.9 + material.roughness))
if material.diffuse_shader == 'TOON' and Level != 3:
tabWrite("brilliance %.3g\n" % (0.01 + material.diffuse_toon_smooth * 0.25))
Bastien Montagne
committed
# Lower diffuse and increase specular for toon effect seems to look better
# in POV-Ray.
frontDiffuse *= 0.5
if material.diffuse_shader == 'MINNAERT' and Level != 3:
#tabWrite("aoi %.3g\n" % material.darkness)
pass # let's keep things simple for now
if material.diffuse_shader == 'FRESNEL' and Level != 3:
#tabWrite("aoi %.3g\n" % material.diffuse_fresnel_factor)
pass # let's keep things simple for now
if material.diffuse_shader == 'LAMBERT' and Level != 3:
Bastien Montagne
committed
# trying to best match lambert attenuation by that constant brilliance value
tabWrite("brilliance 1.8\n")
Bastien Montagne
committed
###########################Specular Shader######################################
# No difference between phong and cook torrence in blender HaHa!
if (material.specular_shader == 'COOKTORR' or
material.specular_shader == 'PHONG'):
tabWrite("phong %.3g\n" % (material.specular_intensity))
tabWrite("phong_size %.3g\n" % (material.specular_hardness / 2 + 0.25))
Bastien Montagne
committed
# POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
elif material.specular_shader == 'BLINN':
# Use blender Blinn's IOR just as some factor for spec intensity
tabWrite("specular %.3g\n" % (material.specular_intensity *
(material.specular_ior / 4.0)))
tabWrite("roughness %.3g\n" % roughness)
#Could use brilliance 2(or varying around 2 depending on ior or factor) too.
elif material.specular_shader == 'TOON':
tabWrite("phong %.3g\n" % (material.specular_intensity * 2.0))
Bastien Montagne
committed
# use extreme phong_size
tabWrite("phong_size %.3g\n" % (0.1 + material.specular_toon_smooth / 2.0))
elif material.specular_shader == 'WARDISO':
Bastien Montagne
committed
# find best suited default constant for brilliance Use both phong and
# specular for some values.
tabWrite("specular %.3g\n" % (material.specular_intensity /
(material.specular_slope + 0.0005)))
# find best suited default constant for brilliance Use both phong and
# specular for some values.
tabWrite("roughness %.4g\n" % (0.0005 + material.specular_slope / 10.0))
# find best suited default constant for brilliance Use both phong and
# specular for some values.
tabWrite("brilliance %.4g\n" % (1.8 - material.specular_slope * 1.8))
####################################################################################
tabWrite("specular 0\n")
tabWrite("specular 1\n")
tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse))
tabWrite("ambient %.3g\n" % material.ambient)
Bastien Montagne
committed
# POV-Ray blends the global value
#tabWrite("ambient rgb <%.3g, %.3g, %.3g>\n" % \
# tuple([c*material.ambient for c in world.ambient_color]))
tabWrite("emission %.3g\n" % material.emit) # New in POV-Ray 3.7
Bastien Montagne
committed
#POV-Ray just ignores roughness if there's no specular keyword
#tabWrite("roughness %.3g\n" % roughness)
Bastien Montagne
committed
if material.pov.conserve_energy:
# added for more realistic shading. Needs some checking to see if it
# really works. --Maurice.
tabWrite("conserve_energy\n")
Maurice Raybaud
committed
if colored_specular_found == True:
tabWrite("metallic\n")
# 'phong 70.0 '
if Level != 1:
if material.raytrace_mirror.use:
raytrace_mirror = material.raytrace_mirror
if raytrace_mirror.reflect_factor:
tabWrite("reflection {\n")
tabWrite("rgb <%.3g, %.3g, %.3g>" % material.mirror_color[:])
Bastien Montagne
committed
if material.pov.mirror_metallic:
tabWrite("metallic %.3g" % (raytrace_mirror.reflect_factor))
Bastien Montagne
committed
if material.pov.mirror_use_IOR: # WORKING ?
# Removed from the line below: gives a more physically correct
# material but needs proper IOR. --Maurice
tabWrite("fresnel 1 ")
tabWrite("falloff %.3g exponent %.3g} " % \
(raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor))
if material.subsurface_scattering.use:
subsurface_scattering = material.subsurface_scattering
Maurice Raybaud
committed
tabWrite("subsurface { translucency <%.3g, %.3g, %.3g> }\n" % (
Maurice Raybaud
committed
(subsurface_scattering.radius[0]),
(subsurface_scattering.radius[1]),
Maurice Raybaud
committed
)
Bastien Montagne
committed
if material.pov.irid_enable:
tabWrite("irid { %.4g thickness %.4g turbulence %.4g }" % \
(material.pov.irid_amount, material.pov.irid_thickness,
material.pov.irid_turbulence))
tabWrite("diffuse 0.8\n")
tabWrite("phong 70.0\n")
#tabWrite("specular 0.2\n")
# This is written into the object
'''
if material and material.transparency_method=='RAYTRACE':
'interior { ior %.3g} ' % material.raytrace_transparency.ior
'''
#tabWrite("crand 1.0\n") # Sand granyness
#tabWrite("metallic %.6f\n" % material.spec)
#tabWrite("phong %.6f\n" % material.spec)
#tabWrite("phong_size %.6f\n" % material.spec)
#tabWrite("brilliance %.6f " % (material.specular_hardness/256.0) # Like hardness
tabWrite("}\n\n")
# Level=2 Means translation of spec and mir levels for when no map influences them
povHasnoSpecularMaps(Level=2)
special_texture_found = False
for t in material.texture_slots:
if t and t.use:
if (t.texture.type == 'IMAGE' and t.texture.image) or t.texture.type != 'IMAGE':
validPath=True
else:
validPath=False
if(t and t.use and validPath and
Bastien Montagne
committed
(t.use_map_specular or t.use_map_raymir or t.use_map_normal or t.use_map_alpha)):
continue # Some texture found
Maurice Raybaud
committed
if special_texture_found or colored_specular_found:
# Level=1 Means No specular nor Mirror reflection
povHasnoSpecularMaps(Level=1)
# Level=3 Means Maximum Spec and Mirror
povHasnoSpecularMaps(Level=3)
Doug Hammond
committed
# DH disabled for now, this isn't the correct context
active_object = None # bpy.context.active_object # does not always work MR
matrix = global_matrix * camera.matrix_world
focal_point = camera.data.dof_distance
# compute resolution
Qsize = float(render.resolution_x) / float(render.resolution_y)
tabWrite("#declare camLocation = <%.6f, %.6f, %.6f>;\n" %
matrix.translation[:])
tabWrite("#declare camLookAt = <%.6f, %.6f, %.6f>;\n" %
Bastien Montagne
committed
tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
tabWrite("camera {\n")
Bastien Montagne
committed
if scene.pov.baking_enable and active_object and active_object.type == 'MESH':
tabWrite("mesh_camera{ 1 3\n") # distribution 3 is what we want here
tabWrite("mesh{%s}\n" % active_object.name)
tabWrite("}\n")
tabWrite("location <0,0,.01>")
tabWrite("direction <0,0,-1>")
tabWrite("location <0, 0, 0>\n")
tabWrite("look_at <0, 0, -1>\n")
tabWrite("right <%s, 0, 0>\n" % - Qsize)
tabWrite("up <0, 1, 0>\n")
tabWrite("angle %f\n" % (360.0 * atan(16.0 / camera.data.lens) / pi))
Bastien Montagne
committed
tabWrite("rotate <%.6f, %.6f, %.6f>\n" % \
tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
tabWrite("translate <%.6f, %.6f, %.6f>\n" % matrix.translation[:])
Bastien Montagne
committed
if camera.data.pov.dof_enable and focal_point != 0:
tabWrite("aperture %.3g\n" % camera.data.pov.dof_aperture)
tabWrite("blur_samples %d %d\n" % \
(camera.data.pov.dof_samples_min, camera.data.pov.dof_samples_max))
tabWrite("variance 1/%d\n" % camera.data.pov.dof_variance)
tabWrite("confidence %.3g\n" % camera.data.pov.dof_confidence)
tabWrite("focal_point <0, 0, %f>\n" % focal_point)
tabWrite("}\n")
# Incremented after each lamp export to declare its target
# currently used for Fresnel diffuse shader as their slope vector:
global lampCount
lampCount = 0
# Get all lamps
for ob in lamps:
lamp = ob.data
matrix = global_matrix * ob.matrix_world
# Color is modified by energy #muiltiplie by 2 for a better match --Maurice
Bastien Montagne
committed
color = tuple([c * lamp.energy * 2.0 for c in lamp.color])
tabWrite("light_source {\n")
tabWrite("< 0,0,0 >\n")
tabWrite("color rgb<%.3g, %.3g, %.3g>\n" % color)
tabWrite("spotlight\n")
tabWrite("falloff %.2f\n" % (degrees(lamp.spot_size) / 2.0)) # 1 TO 179 FOR BOTH
Bastien Montagne
committed
tabWrite("radius %.6f\n" % \
((degrees(lamp.spot_size) / 2.0) * (1.0 - lamp.spot_blend)))
# Blender does not have a tightness equivilent, 0 is most like blender default.
tabWrite("tightness 0\n") # 0:10f
tabWrite("point_at <0, 0, -1>\n")
tabWrite("parallel\n")
tabWrite("point_at <0, 0, -1>\n") # *must* be after 'parallel'
tabWrite("area_illumination\n")
tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
Bastien Montagne
committed
# Area lights have no falloff type, so always use blenders lamp quad equivalent
# for those?
tabWrite("fade_power %d\n" % 2)
size_x = lamp.size
samples_x = lamp.shadow_ray_samples_x
if lamp.shape == 'SQUARE':
size_y = size_x
samples_y = samples_x
else:
size_y = lamp.size_y
samples_y = lamp.shadow_ray_samples_y
Maurice Raybaud
committed
tabWrite("area_light <%.6f,0,0>,<0,%.6f,0> %d, %d\n" % \
(size_x, size_y, samples_x, samples_y))
Maurice Raybaud
committed
if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
if lamp.use_jitter:
tabWrite("jitter\n")
tabWrite("adaptive 1\n")
tabWrite("jitter\n")
Bastien Montagne
committed
# HEMI never has any shadow_method attribute
if(not scene.render.use_shadows or lamp.type == 'HEMI' or
(lamp.type != 'HEMI' and lamp.shadow_method == 'NOSHADOW')):
tabWrite("shadowless\n")
Bastien Montagne
committed
# Sun shouldn't be attenuated. Hemi and area lights have no falloff attribute so they
# are put to type 2 attenuation a little higher above.
if lamp.type not in {'SUN', 'AREA', 'HEMI'}:
tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
tabWrite("fade_power %d\n" % 2) # Use blenders lamp quad equivalent
tabWrite("fade_power %d\n" % 1) # Use blenders lamp linear
Maurice Raybaud
committed
# supposing using no fade power keyword would default to constant, no attenuation.
Bastien Montagne
committed
elif lamp.falloff_type == 'CONSTANT':
Bastien Montagne
committed
# Using Custom curve for fade power 3 for now.
elif lamp.falloff_type == 'CUSTOM_CURVE':
tabWrite("fade_power %d\n" % 4)
tabWrite("}\n")
lampCount += 1
# v(A,B) rotates vector A about origin by vector B.
Bastien Montagne
committed
file.write("#declare lampTarget%s= vrotate(<%.4g,%.4g,%.4g>,<%.4g,%.4g,%.4g>);\n" % \
(lampCount, -(ob.location.x), -(ob.location.y), -(ob.location.z),
ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z))
Bastien Montagne
committed
####################################################################################################
def exportMeta(metas):
# TODO - blenders 'motherball' naming is not supported.
if comments and len(metas) >= 1:
file.write("//--Blob objects--\n\n")
# important because no elements will break parsing.
elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
tabWrite("blob {\n")
tabWrite("threshold %.4g\n" % meta.threshold)
Bastien Montagne
committed
importance = ob.pov.importance_value
material = meta.materials[0] # lame! - blender cant do enything else.
except:
material = None
for elem in elements:
loc = elem.co
stiffness = elem.stiffness
if elem.use_negative:
stiffness = - stiffness
if elem.type == 'BALL':
Bastien Montagne
committed
tabWrite("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % \
(loc.x, loc.y, loc.z, elem.radius, stiffness))
# After this wecould do something simple like...
# "pigment {Blue} }"
# except we'll write the color
elif elem.type == 'ELLIPSOID':
# location is modified by scale
Bastien Montagne
committed
tabWrite("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % \
(loc.x / elem.size_x, loc.y / elem.size_y, loc.z / elem.size_z,
elem.radius, stiffness))
tabWrite("scale <%.6g, %.6g, %.6g> \n" % \
(elem.size_x, elem.size_y, elem.size_z))
if material:
diffuse_color = material.diffuse_color
trans = 1.0 - material.alpha
if material.use_transparency and material.transparency_method == 'RAYTRACE':
povFilter = material.raytrace_transparency.filter * (1.0 - material.alpha)
trans = (1.0 - material.alpha) - povFilter
material_finish = materialNames[material.name]
Bastien Montagne
committed
tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" % \
(diffuse_color[0], diffuse_color[1], diffuse_color[2],
povFilter, trans))
tabWrite("finish {%s}\n" % safety(material_finish, Level=2))
tabWrite("pigment {rgb<1 1 1>} \n")
Bastien Montagne
committed
# Write the finish last.
tabWrite("finish {%s}\n" % (safety(DEF_MAT_NAME, Level=2)))
writeObjectMaterial(material, ob)
writeMatrix(global_matrix * ob.matrix_world)
Maurice Raybaud
committed
# Importance for radiosity sampling added here
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of Metaball block
if comments and len(metas) >= 1:
file.write("\n")
Bastien Montagne
committed
# objectNames = {}
DEF_OBJ_NAME = "Default"
Bastien Montagne
committed
def exportMeshes(scene, sel):
# obmatslist = []
# def hasUniqueMaterial():
# # Grab materials attached to object instances ...
# if hasattr(ob, 'material_slots'):
# for ms in ob.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
Bastien Montagne
committed
# if ms.material in obmatslist:
# return False
# else:
# obmatslist.append(ms.material)
# return True
# def hasObjectMaterial(ob):
# # Grab materials attached to object instances ...
# if hasattr(ob, 'material_slots'):
# for ms in ob.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
Bastien Montagne
committed
# # If there is at least one material slot linked to the object
Bastien Montagne
committed
# # and not the data (mesh), always create a new, "private" data instance.
Bastien Montagne
committed
# return True
# return False
# For objects using local material(s) only!
# This is a mapping between a tuple (dataname, materialnames, ...), and the POV dataname.
Bastien Montagne
committed
# As only objects using:
# * The same data.
# * EXACTLY the same materials, in EXACTLY the same sockets.
# ... can share a same instance in POV export.
Bastien Montagne
committed
obmats2data = {}
Bastien Montagne
committed
def checkObjectMaterials(ob, name, dataname):
if hasattr(ob, 'material_slots'):
has_local_mats = False
key = [dataname]
for ms in ob.material_slots:
Bastien Montagne
committed
key.append(ms.material.name)
if ms.link == 'OBJECT' and not has_local_mats:
has_local_mats = True
else:
# Even if the slot is empty, it is important to grab it...
Bastien Montagne
committed
key.append("")
if has_local_mats:
# If this object uses local material(s), lets find if another object
# using the same data and exactly the same list of materials
# (in the same slots) has already been processed...
Bastien Montagne
committed
# Note that here also, we use object name as new, unique dataname for Pov.
key = tuple(key) # Lists are not hashable...
Bastien Montagne
committed
if key not in obmats2data:
obmats2data[key] = name
return obmats2data[key]
return None
data_ref = {}
Bastien Montagne
committed
def store(scene, ob, name, dataname, matrix):
# The Object needs to be written at least once but if its data is
# already in data_ref this has already been done.
Bastien Montagne
committed
# This func returns the "povray" name of the data, or None
Bastien Montagne
committed
# if no writing is needed.
if ob.is_modified(scene, 'RENDER'):
# Data modified.
# Create unique entry in data_ref by using object name
# (always unique in Blender) as data name.
data_ref[name] = [(name, MatrixAsPovString(matrix))]
return name
# Here, we replace dataname by the value returned by checkObjectMaterials, only if
# it is not evaluated to False (i.e. only if the object uses some local material(s)).
dataname = checkObjectMaterials(ob, name, dataname) or dataname
if dataname in data_ref:
# Data already known, just add the object instance.
data_ref[dataname].append((name, MatrixAsPovString(matrix)))
# No need to write data
return None
else:
# Data not yet processed, create a new entry in data_ref.
data_ref[dataname] = [(name, MatrixAsPovString(matrix))]
return dataname
Bastien Montagne
committed
ob_num = 0
Bastien Montagne
committed
# XXX I moved all those checks here, as there is no need to compute names
Bastien Montagne
committed
# for object we won't export here!
if ob.type in {'LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'}:
for pSys in ob.particle_systems:
if pSys.settings.use_render_emitter:
renderEmitter = True
for mod in [m for m in ob.modifiers if (m is not None) and (m.type == 'PARTICLE_SYSTEM')]:
if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name):
tstart = time.time()
if ob.active_material is not None:
Maurice Raybaud
committed
pmaterial = ob.material_slots[pSys.settings.material - 1].material
for th in pmaterial.texture_slots:
if th and th.use:
if (th.texture.type == 'IMAGE' and th.texture.image) or th.texture.type != 'IMAGE':
if th.use_map_color_diffuse:
texturedHair=1
if pmaterial.strand.use_blender_units:
strandStart = pmaterial.strand.root_size
strandEnd = pmaterial.strand.tip_size
strandStart = pmaterial.strand.root_size / 200.0
strandEnd = pmaterial.strand.tip_size / 200.0
strandShape = pmaterial.strand.shape
else:
pmaterial = "default" # No material assigned in blender, use default one
strandStart = 0.01
strandEnd = 0.01
strandShape = 0.0
# Set the number of particles to render count rather than 3d view display
pSys.set_resolution(scene, ob, 'RENDER')
steps = pSys.settings.draw_step
steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys)
totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) )
#hairCounter = 0
file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs)
for pindex in range(0, totalNumberOfHairs):
#if particle.is_exist and particle.is_visible:
#hairCounter += 1
#controlPointCounter = 0
# Each hair is represented as a separate sphere_sweep in POV-Ray.
file.write('sphere_sweep{')
if pSys.settings.use_hair_bspline:
file.write('b_spline ')
file.write('%i,\n' % (steps + 2)) # +2 because the first point needs tripling to be more than a handle in POV
else:
file.write('linear_spline ')
Maurice Raybaud
committed
#changing world coordinates to object local coordinates by multiplying with inverted matrix
initCo = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, 0))
if ob.active_material is not None:
pmaterial = ob.material_slots[pSys.settings.material-1].material
for th in pmaterial.texture_slots:
Maurice Raybaud
committed
if th and th.use and th.use_map_color_diffuse:
#treat POV textures as bitmaps
if (th.texture.type == 'IMAGE' and th.texture.image and th.texture_coords == 'UV' and ob.data.uv_textures != None): # or (th.texture.pov.tex_pattern_type != 'emulator' and th.texture_coords == 'UV' and ob.data.uv_textures != None):
image=th.texture.image
image_width = image.size[0]
image_height = image.size[1]
image_pixels = image.pixels[:]
uv_co = pSys.uv_on_emitter(mod, pSys.particles[pindex], pindex, 0)
x_co = round(uv_co[0] * (image_width - 1))
y_co = round(uv_co[1] * (image_height - 1))
pixelnumber = (image_width * y_co) + x_co
r = image_pixels[pixelnumber*4]
g = image_pixels[pixelnumber*4+1]
b = image_pixels[pixelnumber*4+2]
a = image_pixels[pixelnumber*4+3]
initColor=(r,g,b,a)
else:
#only overwrite variable for each competing texture for now
initColor=th.texture.evaluate((initCo[0],initCo[1],initCo[2]))
if pSys.settings.clump_factor != 0:
hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1)
hDiameter = strandStart
else:
hDiameter += (strandEnd-strandStart)/(pSys.settings.draw_step+1) #XXX +1 or not?
if step == 0 and pSys.settings.use_hair_bspline:
# Write three times the first point to compensate pov Bezier handling
file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter)))
file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter)))
Campbell Barton
committed
#file.write('<%.6g,%.6g,%.6g>,%.7g' % (particle.location[0], particle.location[1], particle.location[2], abs(hDiameter))) # Useless because particle location is the tip, not the root.
#totalNumberOfHairs += len(pSys.particles)# len(particle.hair_keys)
# Each control point is written out, along with the radius of the
# hair at that point.
file.write('<%.6g,%.6g,%.6g>,%.7g' % (co[0], co[1], co[2], abs(hDiameter)))
# All coordinates except the last need a following comma.
Maurice Raybaud
committed
# Write pigment and alpha (between Pov and Blender alpha 0 and 1 are reversed)
file.write('\npigment{ color rgbf < %.3g, %.3g, %.3g, %.3g> }\n' %(initColor[0], initColor[1], initColor[2], 1.0-initColor[3]))
# End the sphere_sweep declaration for this hair
file.write('}\n')
# All but the final sphere_sweep (each array element) needs a terminating comma.
file.write(',\n')
else:
file.write('\n')
# End the array declaration.
file.write('}\n')
file.write('\n')
if not texturedHair:
# Pick up the hair material diffuse color and create a default POV-Ray hair texture.
file.write('#ifndef (HairTexture)\n')
file.write(' #declare HairTexture = texture {\n')
file.write(' pigment {rgbt <%s,%s,%s,%s>}\n' % (pmaterial.diffuse_color[0], pmaterial.diffuse_color[1], pmaterial.diffuse_color[2], (pmaterial.strand.width_fade + 0.05)))
file.write(' }\n')
file.write('#end\n')
file.write('\n')
# Dynamically create a union of the hairstrands (or a subset of them).
# By default use every hairstrand, commented line is for hand tweaking test renders.
file.write('//Increasing HairStep divides the amount of hair for test renders.\n')
file.write('#ifndef(HairStep) #declare HairStep = 1; #end\n')
file.write('union{\n')
file.write(' #local I = 0;\n')
file.write(' #while (I < %i)\n' % totalNumberOfHairs)
file.write(' object {HairArray[I]')
if not texturedHair:
file.write(' texture{HairTexture}\n')
else:
file.write('\n')
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
# Translucency of the hair:
file.write(' hollow\n')
file.write(' double_illuminate\n')
file.write(' interior {\n')
file.write(' ior 1.45\n')
file.write(' media {\n')
file.write(' scattering { 1, 10*<0.73, 0.35, 0.15> /*extinction 0*/ }\n')
file.write(' absorption 10/<0.83, 0.75, 0.15>\n')
file.write(' samples 1\n')
file.write(' method 2\n')
file.write(' density {\n')
file.write(' color_map {\n')
file.write(' [0.0 rgb <0.83, 0.45, 0.35>]\n')
file.write(' [0.5 rgb <0.8, 0.8, 0.4>]\n')
file.write(' [1.0 rgb <1,1,1>]\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' #local I = I + HairStep;\n')
file.write(' #end\n')
writeMatrix(global_matrix * ob.matrix_world)
file.write('}')
print('Totals hairstrands written: %i' % totalNumberOfHairs)
print('Number of tufts (particle systems)', len(ob.particle_systems))
# Set back the displayed number of particles to preview count
pSys.set_resolution(scene, ob, 'PREVIEW')
if renderEmitter == False:
continue #don't render mesh, skip to next object.
except:
# happens when curves cant be made into meshes because of no-data
continue
Bastien Montagne
committed
importance = ob.pov.importance_value
me_faces = me.tessfaces[:]
Bastien Montagne
committed
#############################################
# Generating a name for object just like materials to be able to use it
# (baking for now or anything else).
Maurice Raybaud
committed
# XXX I don't understand that: if we are here, sel if a non-empty iterable,
Bastien Montagne
committed
# so this condition is always True, IMO -- mont29
if sel:
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.data.name
else:
name_orig = DEF_OBJ_NAME
dataname_orig = DEF_OBJ_NAME
name = string_strip_hyphen(bpy.path.clean_name(name_orig))
dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
Bastien Montagne
committed
## for slot in ob.material_slots:
## if slot.material is not None and slot.link == 'OBJECT':
Bastien Montagne
committed
## obmaterial = slot.material
#############################################
info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name))
#if ob.type != 'MESH':
# continue
matrix = global_matrix * ob.matrix_world
Bastien Montagne
committed
povdataname = store(scene, ob, name, dataname, matrix)
if povdataname is None:
print("This is an instance")
continue
print("Writing Down First Occurence")
uv_textures = me.tessface_uv_textures
if len(uv_textures) > 0:
if me.uv_textures.active and uv_textures.active.data:
uv_layer = uv_textures.active.data
else:
#vcol_layer = me.vertex_colors.active.data
vcol_layer = me.tessface_vertex_colors.active.data
faces_verts = [f.vertices[:] for f in me_faces]
faces_normals = [f.normal[:] for f in me_faces]
verts_normals = [v.normal[:] for v in me.vertices]
quadCount = sum(1 for f in faces_verts if len(f) == 4)
# Use named declaration to allow reference e.g. for baking. MR
file.write("\n")
Bastien Montagne
committed
tabWrite("#declare %s =\n" % povdataname)
tabWrite("mesh2 {\n")
tabWrite("vertex_vectors {\n")
tabWrite("%d" % len(me.vertices)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
else:
file.write(", ")
file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
Constantin Rahn
committed
#tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
file.write("\n")
tabWrite("}\n")
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
# [-1] is a dummy index, use a list so we can modify in place
if f.use_smooth: # Use vertex normals
for v in fv:
key = verts_normals[v]
uniqueNormals[key] = [-1]
key = faces_normals[fi]
uniqueNormals[key] = [-1]
tabWrite("normal_vectors {\n")
tabWrite("%d" % len(uniqueNormals)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count
else:
file.write(", ")
file.write("<%.6f, %.6f, %.6f>" % no) # vert count
file.write("\n")
tabWrite("}\n")
# Vertex colors
vertCols = {} # Use for material colors also.
if uv_layer:
# Generate unique UV's
uniqueUVs = {}
#n = 0
for fi, uv in enumerate(uv_layer):
if len(faces_verts[fi]) == 4:
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2], uv_layer[fi].uv[3]
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2]
tabWrite("uv_vectors {\n")
tabWrite("%d" % len(uniqueUVs)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f>" % uv)
else:
file.write(", ")
file.write("<%.6f, %.6f>" % uv)
index[0] = idx
idx += 1
'''
else:
# Just add 1 dummy vector, no real UV's
Constantin Rahn
committed
tabWrite('1') # vert count
file.write("\n")
tabWrite("}\n")
#Write down vertex colors as a texture for each vertex
tabWrite("texture_list {\n")
tabWrite("%d\n" % (((len(me_faces)-quadCount) * 3 )+ quadCount * 4)) # works only with tris and quad mesh for now
VcolIdx=0
if comments:
file.write("\n //Vertex colors: one simple pigment texture per vertex\n")
for fi, f in enumerate(me_faces):
# annoying, index may be invalid
try:
material = me_materials[material_index]
except:
material = None
if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now
col = vcol_layer[fi]
if len(faces_verts[fi]) == 4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
for col in cols:
key = col[0], col[1], col[2], material_index # Material index!
VcolIdx+=1
vertCols[key] = [VcolIdx]
if linebreaksinlists:
tabWrite("texture {pigment{ color rgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2]))
else:
tabWrite("texture {pigment{ color rgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2]))
tabStr = tab * tabLevel
Maurice Raybaud
committed
# Multiply diffuse with SSS Color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
Maurice Raybaud
committed
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \
material_index
vertCols[key] = [-1]
else:
diffuse_color = material.diffuse_color[:]
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \
material_index
vertCols[key] = [-1]
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
tabWrite("\n}\n")
# Face indices
tabWrite("\nface_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
material_index = f.material_index
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
if vcol_layer:
col = vcol_layer[fi]
if len(fv) == 4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
if not me_materials or me_materials[material_index] is None: # No materials
for i1, i2, i3 in indices:
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
file.write(",\n")
# vert count
file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count
else:
material = me_materials[material_index]
for i1, i2, i3 in indices:
if me.vertex_colors: #and material.use_vertex_color_paint:
# Color per vertex - vertex color
col1 = cols[i1]
col2 = cols[i2]
col3 = cols[i3]
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
else:
# Color per material - flat material color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
else:
diffuse_color = material.diffuse_color[:]
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
diffuse_color[2], f.material_index][0]
# ci are zero based index so we'll subtract 1 from them
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>, %d,%d,%d" % \
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
file.write("\n")
tabWrite("}\n")
# normal_indices indices
tabWrite("normal_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
for i1, i2, i3 in indices:
if me_faces[fi].use_smooth:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
idx = uniqueNormals[faces_normals[fi]][0]
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
file.write("\n")
tabWrite("}\n")
if uv_layer:
tabWrite("uv_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
uv = uv_layer[fi]
if len(faces_verts[fi]) == 4:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:]
else:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:]
for i1, i2, i3 in indices:
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
file.write("\n")
tabWrite("}\n")
if me.materials:
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of mesh block
# No vertex colors, so write material colors as vertex colors
for i, material in enumerate(me_materials):
if material:
Maurice Raybaud
committed
# Multiply diffuse with SSS Color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
Maurice Raybaud
committed
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
vertCols[key] = [-1]
else:
diffuse_color = material.diffuse_color[:]
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
vertCols[key] = [-1]
Maurice Raybaud
committed
idx = 0
LocalMaterialNames = []
Maurice Raybaud
committed
for col, index in vertCols.items():
#if me_materials:
mater = me_materials[col[3]]
Maurice Raybaud
committed
material_finish = DEF_MAT_NAME # not working properly,
trans = 0.0
Maurice Raybaud
committed
else:
material_finish = materialNames[mater.name]
if mater.use_transparency:
trans = 1.0 - mater.alpha
Maurice Raybaud
committed
else:
trans = 0.0
if (mater.specular_color.s == 0.0):
Maurice Raybaud
committed
colored_specular_found = False
else:
colored_specular_found = True
if mater.use_transparency and mater.transparency_method == 'RAYTRACE':
povFilter = mater.raytrace_transparency.filter * (1.0 - mater.alpha)
trans = (1.0 - mater.alpha) - povFilter
Maurice Raybaud
committed
else:
povFilter = 0.0
##############SF
texturesDif = ""
texturesSpec = ""
texturesNorm = ""
texturesAlpha = ""
#proceduralFlag=False
for t in mater.texture_slots:
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
if t and t.use and t.texture.type != 'IMAGE' and t.texture.type != 'NONE':
proceduralFlag=True
image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(t.texture.name))
if image_filename:
if t.use_map_color_diffuse:
texturesDif = image_filename
# colvalue = t.default_value # UNUSED
t_dif = t
if t_dif.texture.pov.tex_gamma_enable:
imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value)
if t.use_map_specular or t.use_map_raymir:
texturesSpec = image_filename
# colvalue = t.default_value # UNUSED
t_spec = t
if t.use_map_normal:
texturesNorm = image_filename
# colvalue = t.normal_factor * 10.0 # UNUSED
#textNormName=t.texture.image.name + ".normal"
#was the above used? --MR
t_nor = t
if t.use_map_alpha:
texturesAlpha = image_filename
# colvalue = t.alpha_factor * 10.0 # UNUSED
#textDispName=t.texture.image.name + ".displ"
#was the above used? --MR
t_alpha = t
if t and t.texture.type == 'IMAGE' and t.use and t.texture.image and t.texture.pov.tex_pattern_type == 'emulator':
proceduralFlag=False
if t.texture.image.packed_file:
orig_image_filename=t.texture.image.filepath_raw
workDir=os.path.dirname(__file__)
previewDir=os.path.join(workDir, "preview")
unpackedfilename= os.path.join(previewDir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(t.texture.name)))))
if not os.path.exists(unpackedfilename):
# record which images that were newly copied and can be safely
# cleaned up
unpacked_images.append(unpackedfilename)
t.texture.image.filepath_raw=unpackedfilename
t.texture.image.save()
image_filename = unpackedfilename
t.texture.image.filepath_raw=orig_image_filename
else:
image_filename = path_image(t.texture.image)
Maurice Raybaud
committed
# IMAGE SEQUENCE BEGINS
if image_filename:
if bpy.data.images[t.texture.image.name].source == 'SEQUENCE':
korvaa = "." + str(bpy.data.textures[t.texture.name].image_user.frame_offset + 1).zfill(3) + "."
image_filename = image_filename.replace(".001.", korvaa)
print(" seq debug ")
print(image_filename)
# IMAGE SEQUENCE ENDS
Maurice Raybaud
committed
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
imgGamma = ""
if image_filename:
if t.use_map_color_diffuse:
texturesDif = image_filename
# colvalue = t.default_value # UNUSED
t_dif = t
if t_dif.texture.pov.tex_gamma_enable:
imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value)
if t.use_map_specular or t.use_map_raymir:
texturesSpec = image_filename
# colvalue = t.default_value # UNUSED
t_spec = t
if t.use_map_normal:
texturesNorm = image_filename
# colvalue = t.normal_factor * 10.0 # UNUSED
#textNormName=t.texture.image.name + ".normal"
#was the above used? --MR
t_nor = t
if t.use_map_alpha:
texturesAlpha = image_filename
# colvalue = t.alpha_factor * 10.0 # UNUSED
#textDispName=t.texture.image.name + ".displ"
#was the above used? --MR
t_alpha = t
####################################################################################
file.write("\n")
# THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN.
# --MR
currentMatName = string_strip_hyphen(materialNames[mater.name])
Maurice Raybaud
committed
LocalMaterialNames.append(currentMatName)
file.write("\n #declare MAT_%s = \ntexture{\n" % currentMatName)
################################################################################
if mater.pov.replacement_text != "":
file.write("%s\n" % mater.pov.replacement_text)
#################################################################################
if mater.diffuse_shader == 'MINNAERT':
Maurice Raybaud
committed
tabWrite("\n")
tabWrite("aoi\n")
tabWrite("texture_map {\n")
tabWrite("[%.3g finish {diffuse %.3g}]\n" % \
(mater.darkness / 2.0, 2.0 - mater.darkness))
tabWrite("[%.3g\n" % (1.0 - (mater.darkness / 2.0)))
Maurice Raybaud
committed
if mater.diffuse_shader == 'FRESNEL':
Maurice Raybaud
committed
# For FRESNEL diffuse in POV, we'll layer slope patterned textures
# with lamp vector as the slope vector and nest one slope per lamp
# into each texture map's entry.
c = 1
while (c <= lampCount):
tabWrite("slope { lampTarget%s }\n" % (c))
tabWrite("texture_map {\n")
# Diffuse Fresnel value and factor go up to five,
# other kind of values needed: used the number 5 below to remap
tabWrite("[%.3g finish {diffuse %.3g}]\n" % \
((5.0 - mater.diffuse_fresnel) / 5,
(mater.diffuse_intensity *
((5.0 - mater.diffuse_fresnel_factor) / 5))))
tabWrite("[%.3g\n" % ((mater.diffuse_fresnel_factor / 5) *
(mater.diffuse_fresnel / 5.0)))
Maurice Raybaud
committed
c += 1
# if shader is a 'FRESNEL' or 'MINNAERT': slope pigment pattern or aoi
# and texture map above, the rest below as one of its entry
if texturesSpec != "" or texturesAlpha != "":
if texturesSpec != "":
# tabWrite("\n")
tabWrite("pigment_pattern {\n")
if texturesSpec and texturesSpec.startswith("PAT_"):
tabWrite("function{f%s(x,y,z).grey}" %texturesSpec)
else:
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the
# scale is not the same in blender and POV
mappingSpec = "translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>\n" % \
(-t_spec.offset.x, t_spec.offset.y, t_spec.offset.z,
1.0 / t_spec.scale.x, 1.0 / t_spec.scale.y,
1.0 / t_spec.scale.z)
tabWrite("uv_mapping image_map{%s \"%s\" %s}\n" % \
(imageFormat(texturesSpec), texturesSpec, imgMap(t_spec)))
tabWrite("%s\n" % mappingSpec)
Maurice Raybaud
committed
tabWrite("}\n")
tabWrite("texture_map {\n")
tabWrite("[0 \n")
if texturesDif == "":
if texturesAlpha != "":
tabWrite("\n")
if texturesAlpha and texturesAlpha.startswith("PAT_"):
tabWrite("function{f%s(x,y,z).transmit}\n" %texturesAlpha)
else:
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the
# scale is not the same in blender and POV
mappingAlpha = " translate <%.4g, %.4g, %.4g> " \
"scale <%.4g, %.4g, %.4g>\n" % \
(-t_alpha.offset.x, -t_alpha.offset.y,
t_alpha.offset.z, 1.0 / t_alpha.scale.x,
1.0 / t_alpha.scale.y, 1.0 / t_alpha.scale.z)
tabWrite("pigment {pigment_pattern {uv_mapping image_map" \
"{%s \"%s\" %s}%s" % \
(imageFormat(texturesAlpha), texturesAlpha,
imgMap(t_alpha), mappingAlpha))
Maurice Raybaud
committed
tabWrite("}\n")
tabWrite("pigment_map {\n")
tabWrite("[0 color rgbft<0,0,0,1,1>]\n")
tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \
(col[0], col[1], col[2], povFilter, trans))
tabWrite("}\n")
tabWrite("}\n")
Maurice Raybaud
committed
else:
Maurice Raybaud
committed
Maurice Raybaud
committed
tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \
(col[0], col[1], col[2], povFilter, trans))
Maurice Raybaud
committed
Maurice Raybaud
committed
if texturesSpec != "":
# Level 1 is no specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=1)))
Maurice Raybaud
committed
Maurice Raybaud
committed
else:
# Level 2 is translated spec
tabWrite("finish {%s}\n" % (safety(material_finish, Level=2)))
Maurice Raybaud
committed
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
else:
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the
# scale is not the same in blender and POV
mappingDif = ("translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % \
(-t_dif.offset.x, -t_dif.offset.y, t_dif.offset.z,
1.0 / t_dif.scale.x, 1.0 / t_dif.scale.y,
1.0 / t_dif.scale.z))
if texturesAlpha != "":
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the
# scale is not the same in blender and POV
mappingAlpha = " translate <%.4g,%.4g,%.4g> " \
"scale <%.4g,%.4g,%.4g>" % \
(-t_alpha.offset.x, -t_alpha.offset.y,
t_alpha.offset.z, 1.0 / t_alpha.scale.x,
1.0 / t_alpha.scale.y, 1.0 / t_alpha.scale.z)
tabWrite("pigment {\n")
tabWrite("pigment_pattern {\n")
if texturesAlpha and texturesAlpha.startswith("PAT_"):
tabWrite("function{f%s(x,y,z).transmit}\n" %texturesAlpha)
else:
tabWrite("uv_mapping image_map{%s \"%s\" %s}%s}\n" % \
(imageFormat(texturesAlpha), texturesAlpha,
imgMap(t_alpha), mappingAlpha))
Maurice Raybaud
committed
tabWrite("pigment_map {\n")
tabWrite("[0 color rgbft<0,0,0,1,1>]\n")
#if texturesAlpha and texturesAlpha.startswith("PAT_"):
#tabWrite("[1 pigment{%s}]\n" %texturesDif)
if texturesDif and not texturesDif.startswith("PAT_"):
tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \
(imageFormat(texturesDif), texturesDif,
(imgGamma + imgMap(t_dif)), mappingDif))
elif texturesDif and texturesDif.startswith("PAT_"):
tabWrite("[1 %s]\n" %texturesDif)
Maurice Raybaud
committed
tabWrite("}\n")
tabWrite("}\n")
if texturesAlpha and texturesAlpha.startswith("PAT_"):
tabWrite("}\n")
Maurice Raybaud
committed
else:
if texturesDif and texturesDif.startswith("PAT_"):
tabWrite("pigment{%s}\n" %texturesDif)
else:
tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s}\n" % \
(imageFormat(texturesDif), texturesDif,
(imgGamma + imgMap(t_dif)), mappingDif))
Maurice Raybaud
committed
if texturesSpec != "":
# Level 1 is no specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=1)))
Maurice Raybaud
committed
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
else:
# Level 2 is translated specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=2)))
## scale 1 rotate y*0
#imageMap = ("{image_map {%s \"%s\" %s }\n" % \
# (imageFormat(textures),textures,imgMap(t_dif)))
#tabWrite("uv_mapping pigment %s} %s finish {%s}\n" % \
# (imageMap,mapping,safety(material_finish)))
#tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s} " \
# "finish {%s}\n" % \
# (imageFormat(texturesDif), texturesDif, imgMap(t_dif),
# mappingDif, safety(material_finish)))
if texturesNorm != "":
## scale 1 rotate y*0
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the
# scale is not the same in blender and POV
mappingNor = " translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % \
(-t_nor.offset.x, -t_nor.offset.y, t_nor.offset.z,
1.0 / t_nor.scale.x, 1.0 / t_nor.scale.y,
1.0 / t_nor.scale.z)
#imageMapNor = ("{bump_map {%s \"%s\" %s mapping}" % \
# (imageFormat(texturesNorm),texturesNorm,imgMap(t_nor)))
#We were not using the above maybe we should?
if texturesNorm and texturesNorm.startswith("PAT_"):
tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g}\n" %(texturesNorm, t_nor.normal_factor * 10))
else:
tabWrite("normal {uv_mapping bump_map " \
"{%s \"%s\" %s bump_size %.4g }%s}\n" % \
(imageFormat(texturesNorm), texturesNorm, imgMap(t_nor),
t_nor.normal_factor * 10, mappingNor))
Maurice Raybaud
committed
if texturesSpec != "":
tabWrite("]\n")
##################Second index for mapping specular max value###############
tabWrite("[1 \n")
if texturesDif == "" and mater.pov.replacement_text == "":
Maurice Raybaud
committed
if texturesAlpha != "":
# POV-Ray "scale" is not a number of repetitions factor, but its inverse,
# a standard scale factor.
# Offset seems needed relatively to scale so probably center of the scale
# is not the same in blender and POV
# Strange that the translation factor for scale is not the same as for
# translate.
# TODO: verify both matches with blender internal.
mappingAlpha = " translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>\n" % \
(-t_alpha.offset.x, -t_alpha.offset.y, t_alpha.offset.z,
1.0 / t_alpha.scale.x, 1.0 / t_alpha.scale.y,
1.0 / t_alpha.scale.z)
if texturesAlpha and texturesAlpha.startswith("PAT_"):
tabWrite("function{f%s(x,y,z).transmit}\n" %texturesAlpha)
else:
tabWrite("pigment {pigment_pattern {uv_mapping image_map" \
"{%s \"%s\" %s}%s}\n" % \
(imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha),
mappingAlpha))
Maurice Raybaud
committed
tabWrite("pigment_map {\n")
tabWrite("[0 color rgbft<0,0,0,1,1>]\n")
tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \
(col[0], col[1], col[2], povFilter, trans))
tabWrite("}\n")
tabWrite("}\n")
Maurice Raybaud
committed
else:
tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \
(col[0], col[1], col[2], povFilter, trans))
if texturesSpec != "":
# Level 3 is full specular
tabWrite("finish {%s}\n" % (safety(material_finish, Level=3)))
Loading
Loading full blame...