Newer
Older
sim_sizeX, sim_sizeY, sim_sizeZ = mydf3.size()
for x in range(sim_sizeX):
for y in range(sim_sizeY):
for z in range(sim_sizeZ):
mydf3.set(x, y, z, channeldata[((z * sim_sizeY + y) * sim_sizeX + x)])
mydf3.exportDF3(smokePath)
print('Binary smoke.df3 file written in preview directory')
if comments:
file.write("\n//--Smoke--\n\n")
# Note: We start with a default unit cube.
# This is mandatory to read correctly df3 data - otherwise we could just directly use bbox
# coordinates from the start, and avoid scale/translate operations at the end...
file.write("box{<0,0,0>, <1,1,1>\n")
file.write(" pigment{ rgbt 1 }\n")
file.write(" hollow\n")
file.write(" interior{ //---------------------\n")
file.write(" media{ method 3\n")
file.write(" emission <1,1,1>*1\n")# 0>1 for dark smoke to white vapour
file.write(" scattering{ 1, // Type\n")
file.write(" <1,1,1>*0.1\n")
file.write(" density{density_file df3 \"%s\"\n" % (smokePath))
file.write(" color_map {\n")
file.write(" [0.00 rgb 0]\n")
file.write(" [0.05 rgb 0]\n")
file.write(" [0.20 rgb 0.2]\n")
file.write(" [0.30 rgb 0.6]\n")
file.write(" [0.40 rgb 1]\n")
file.write(" [1.00 rgb 1]\n")
file.write(" } // end color_map\n")
file.write(" } // end of density\n")
file.write(" samples %i // higher = more precise\n" % resolution)
file.write(" } // end of media --------------------------\n")
file.write(" } // end of interior\n")
# START OF TRANSFORMATIONS
# Size to consider here are bbox dimensions (i.e. still in object space, *before* applying
# loc/rot/scale and other transformations (like parent stuff), aka matrix_world).
bbox = smoke_obj.bound_box
dim = [abs(bbox[6][0] - bbox[0][0]), abs(bbox[6][1] - bbox[0][1]), abs(bbox[6][2] - bbox[0][2])]
# We scale our cube to get its final size and shapes but still in *object* space (same as Blender's bbox).
file.write("scale<%.6g,%.6g,%.6g>\n" % (dim[0], dim[1], dim[2]))
# We offset our cube such that (0,0,0) coordinate matches Blender's object center.
file.write("translate<%.6g,%.6g,%.6g>\n" % (bbox[0][0], bbox[0][1], bbox[0][2]))
# We apply object's transformations to get final loc/rot/size in world space!
# Note: we could combine the two previous transformations with this matrix directly...
writeMatrix(global_matrix @ smoke_obj.matrix_world)
# END OF TRANSFORMATIONS
#file.write(" interpolate 1\n")
#file.write(" frequency 0\n")
#file.write(" }\n")
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 {'LIGHT', 'CAMERA', #'EMPTY', #empties can bear dupligroups
'META', 'ARMATURE', 'LATTICE'}):
for mod in ob.modifiers:
if mod and hasattr(mod, 'smoke_type'):
smokeFlag=True
if (mod.smoke_type == 'DOMAIN'):
exportSmoke(ob.name)
break # don't render domain mesh or flow emitter mesh, skip to next object.
# Export Hair
renderEmitter = True
if hasattr(ob, 'particle_systems'):
renderEmitter = False
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()
texturedHair=0
if ob.material_slots[pSys.settings.material - 1].material and ob.active_material is not None:
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
else: # Blender unit conversion
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.display_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 ')
file.write('%i,\n' % (steps))
#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.material_slots[pSys.settings.material - 1].material and ob.active_material is not None:
pmaterial = ob.material_slots[pSys.settings.material-1].material
for th in pmaterial.texture_slots:
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 is not None): # or (th.texture.pov.tex_pattern_type != 'emulator' and th.texture_coords == 'UV' and ob.data.uv_textures is not 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]
else:
#only overwrite variable for each competing texture for now
initColor=th.texture.evaluate((initCo[0],initCo[1],initCo[2]))
for step in range(0, steps):
co = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, step))
#for controlPoint in particle.hair_keys:
if pSys.settings.clump_factor != 0:
hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1)
elif step == 0:
hDiameter = strandStart
else:
hDiameter += (strandEnd-strandStart)/(pSys.settings.display_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)))
#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.
#file.write(',\n')
#controlPointCounter += 1
#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.
if step != steps - 1:
file.write(',\n')
else:
if texturedHair:
# Write pigment and alpha (between Pov and Blender alpha 0 and 1 are reversed)
Maurice Raybaud
committed
file.write('\npigment{ color srgbf < %.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.
if pindex != totalNumberOfHairs:
file.write(',\n')
else:
file.write('\n')
# End the array declaration.
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')
Maurice Raybaud
committed
file.write(' pigment {srgbt <%s,%s,%s,%s>}\n' % (pmaterial.diffuse_color[0], pmaterial.diffuse_color[1], pmaterial.diffuse_color[2], (pmaterial.strand.width_fade + 0.05)))
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
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')
# 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')
Maurice Raybaud
committed
file.write(' density {cylindrical\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)
Bastien Montagne
committed
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.
#############################################
# Generating a name for object just like materials to be able to use it
# (baking for now or anything else).
# XXX I don't understand that if we are here, sel if a non-empty iterable,
# so this condition is always True, IMO -- mont29
Maurice Raybaud
committed
if ob.data:
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.data.name
elif ob.is_instancer:
if ob.instance_type == 'COLLECTION':
Maurice Raybaud
committed
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.instance_collection.name
Maurice Raybaud
committed
else:
#hoping only dupligroups have several source datablocks
ob.dupli_list_create(scene)
for eachduplicate in ob.dupli_list:
dataname_orig = "DATA" + eachduplicate.object.name
Maurice Raybaud
committed
elif ob.type == 'EMPTY':
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.name
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))
## for slot in ob.material_slots:
## if slot.material is not None and slot.link == 'OBJECT':
## obmaterial = slot.material
#############################################
if info_callback:
info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name))
#if ob.type != 'MESH':
# continue
# me = ob.data
matrix = global_matrix @ ob.matrix_world
povdataname = store(scene, ob, name, dataname, matrix)
if povdataname is None:
print("This is an instance of " + name)
print("Writing Down First Occurrence of " + name)
############################################Povray Primitives
# special exportCurves() function takes care of writing
# lathe, sphere_sweep, birail, and loft except with modifiers
# converted to mesh
if not ob.is_modified(scene, 'RENDER'):
if ob.type == 'CURVE' and (ob.pov.curveshape in
{'lathe', 'sphere_sweep', 'loft'}):
continue #Don't render proxy mesh, skip to next object
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
if ob.pov.object_as == 'ISOSURFACE':
tabWrite("#declare %s = isosurface{ \n"% povdataname)
tabWrite("function{ \n")
textName = ob.pov.iso_function_text
if textName:
node_tree = bpy.context.scene.node_tree
for node in node_tree.nodes:
if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
for inp in node.inputs:
if inp:
tabWrite("#declare %s = %.6g;\n"%(inp.name,inp.default_value))
text = bpy.data.texts[textName]
for line in text.lines:
split = line.body.split()
if split[0] != "#declare":
tabWrite("%s\n"%line.body)
else:
tabWrite("abs(x) - 2 + y")
tabWrite("}\n")
tabWrite("threshold %.6g\n"%ob.pov.threshold)
tabWrite("max_gradient %.6g\n"%ob.pov.max_gradient)
tabWrite("accuracy %.6g\n"%ob.pov.accuracy)
tabWrite("contained_by { ")
if ob.pov.contained_by == "sphere":
tabWrite("sphere {0,%.6g}}\n"%ob.pov.container_scale)
else:
tabWrite("box {-%.6g,%.6g}}\n"%(ob.pov.container_scale,ob.pov.container_scale))
if ob.pov.all_intersections:
tabWrite("all_intersections\n")
else:
if ob.pov.max_trace > 1:
tabWrite("max_trace %.6g\n"%ob.pov.max_trace)
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
tabWrite("scale %.6g\n"%(1/ob.pov.container_scale))
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
if ob.pov.object_as == 'SUPERELLIPSOID':
tabWrite("#declare %s = superellipsoid{ <%.4f,%.4f>\n"%(povdataname,ob.pov.se_n2,ob.pov.se_n1))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'SUPERTORUS':
rMajor = ob.pov.st_major_radius
rMinor = ob.pov.st_minor_radius
ring = ob.pov.st_ring
cross = ob.pov.st_cross
accuracy=ob.pov.st_accuracy
gradient=ob.pov.st_max_gradient
############Inline Supertorus macro
file.write("#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n")
file.write(" #local CP = 2/MinorControl;\n")
file.write(" #local RP = 2/MajorControl;\n")
file.write(" isosurface {\n")
file.write(" function { pow( pow(abs(pow(pow(abs(x),RP) + pow(abs(z),RP), 1/RP) - RMj),CP) + pow(abs(y),CP) ,1/CP) - RMn }\n")
file.write(" threshold 0\n")
file.write(" contained_by {box {<-RMj-RMn,-RMn,-RMj-RMn>, < RMj+RMn, RMn, RMj+RMn>}}\n")
file.write(" #if(MaxGradient >= 1)\n")
file.write(" max_gradient MaxGradient\n")
file.write(" #else\n")
file.write(" evaluate 1, 10, 0.1\n")
file.write(" #end\n")
file.write(" accuracy Accuracy\n")
file.write(" }\n")
file.write("#end\n")
############
tabWrite("#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"%(povdataname,rMajor,rMinor,ring,cross,accuracy,gradient))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'PLANE':
tabWrite("#declare %s = plane{ <0,0,1>,1\n"%povdataname)
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
if ob.pov.object_as == 'BOX':
tabWrite("#declare %s = box { -1,1\n"%povdataname)
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'CONE':
br = ob.pov.cone_base_radius
cr = ob.pov.cone_cap_radius
bz = ob.pov.cone_base_z
cz = ob.pov.cone_cap_z
tabWrite("#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"%(povdataname,bz,br,cz,cr))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'CYLINDER':
Maurice Raybaud
committed
r = ob.pov.cylinder_radius
x2 = ob.pov.cylinder_location_cap[0]
y2 = ob.pov.cylinder_location_cap[1]
z2 = ob.pov.cylinder_location_cap[2]
tabWrite("#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"%(
povdataname,
x2,
y2,
z2,
r))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
Maurice Raybaud
committed
#cylinders written at origin, translated below
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'HEIGHT_FIELD':
data = ""
filename = ob.pov.hf_filename
data += '"%s"'%filename
gamma = ' gamma %.4f'%ob.pov.hf_gamma
data += gamma
if ob.pov.hf_premultiplied:
data += ' premultiplied on'
if ob.pov.hf_smooth:
data += ' smooth'
if ob.pov.hf_water > 0:
data += ' water_level %.4f'%ob.pov.hf_water
#hierarchy = ob.pov.hf_hierarchy
tabWrite('#declare %s = height_field { %s\n'%(povdataname,data))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
tabWrite("rotate x*90\n")
tabWrite("translate <-0.5,0.5,0>\n")
tabWrite("scale <0,-1,0>\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
if ob.pov.object_as == 'SPHERE':
tabWrite("#declare %s = sphere { 0,%6f\n"%(povdataname,ob.pov.sphere_radius))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'TORUS':
tabWrite("#declare %s = torus { %.4f,%.4f\n"%(povdataname,ob.pov.torus_major_radius,ob.pov.torus_minor_radius))
povMatName = "Default_texture"
if ob.active_material:
#povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
try:
material = ob.active_material
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#tabWrite("texture {%s}\n"%povMatName)
write_object_modifiers(scene,ob,file)
tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'PARAMETRIC':
tabWrite("#declare %s = parametric {\n"%povdataname)
tabWrite("function { %s }\n"%ob.pov.x_eq)
tabWrite("function { %s }\n"%ob.pov.y_eq)
tabWrite("function { %s }\n"%ob.pov.z_eq)
tabWrite("<%.4f,%.4f>, <%.4f,%.4f>\n"%(ob.pov.u_min,ob.pov.v_min,ob.pov.u_max,ob.pov.v_max))
if ob.pov.contained_by == "sphere":
tabWrite("contained_by { sphere{0, 2} }\n")
tabWrite("contained_by { box{-2, 2} }\n")
tabWrite("max_gradient %.6f\n"%ob.pov.max_gradient)
tabWrite("accuracy %.6f\n"%ob.pov.accuracy)
tabWrite("precompute 10 x,y,z\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
if ob.pov.object_as == 'POLYCIRCLE':
#TODO write below macro Once:
#if write_polytocircle_macro_once == 0:
file.write("/****************************\n")
file.write("This macro was written by 'And'.\n")
file.write("Link:(http://news.povray.org/povray.binaries.scene-files/)\n")
file.write("****************************/\n")
file.write("//from math.inc:\n")
file.write("#macro VPerp_Adjust(V, Axis)\n")
file.write(" vnormalize(vcross(vcross(Axis, V), Axis))\n")
file.write("#end\n")
file.write("//Then for the actual macro\n")
file.write("#macro Shape_Slice_Plane_2P_1V(point1, point2, clip_direct)\n")
file.write("#local p1 = point1 + <0,0,0>;\n")
file.write("#local p2 = point2 + <0,0,0>;\n")
file.write("#local clip_v = vnormalize(clip_direct + <0,0,0>);\n")
file.write("#local direct_v1 = vnormalize(p2 - p1);\n")
file.write("#if(vdot(direct_v1, clip_v) = 1)\n")
file.write(' #error "Shape_Slice_Plane_2P_1V error: Can\'t decide plane"\n')
file.write("#end\n\n")
file.write("#local norm = -vnormalize(clip_v - direct_v1*vdot(direct_v1,clip_v));\n")
file.write("#local d = vdot(norm, p1);\n")
file.write("plane{\n")
file.write("norm, d\n")
file.write("}\n")
file.write("#end\n\n")
file.write("//polygon to circle\n")
file.write("#macro Shape_Polygon_To_Circle_Blending(_polygon_n, _side_face, _polygon_circumscribed_radius, _circle_radius, _height)\n")
file.write("#local n = int(_polygon_n);\n")
file.write("#if(n < 3)\n")
file.write(" #error ""\n")
file.write("#end\n\n")
file.write("#local front_v = VPerp_Adjust(_side_face, z);\n")
file.write("#if(vdot(front_v, x) >= 0)\n")
file.write(" #local face_ang = acos(vdot(-y, front_v));\n")
file.write("#else\n")
file.write(" #local face_ang = -acos(vdot(-y, front_v));\n")
file.write("#end\n")
file.write("#local polyg_ext_ang = 2*pi/n;\n")
file.write("#local polyg_outer_r = _polygon_circumscribed_radius;\n")
file.write("#local polyg_inner_r = polyg_outer_r*cos(polyg_ext_ang/2);\n")
file.write("#local cycle_r = _circle_radius;\n")
file.write("#local h = _height;\n")
file.write("#if(polyg_outer_r < 0 | cycle_r < 0 | h <= 0)\n")
file.write(' #error "error: each side length must be positive"\n')
file.write("#end\n\n")
file.write("#local multi = 1000;\n")
file.write("#local poly_obj =\n")
file.write("polynomial{\n")
file.write("4,\n")
file.write("xyz(0,2,2): multi*1,\n")
file.write("xyz(2,0,1): multi*2*h,\n")
file.write("xyz(1,0,2): multi*2*(polyg_inner_r-cycle_r),\n")
file.write("xyz(2,0,0): multi*(-h*h),\n")
file.write("xyz(0,0,2): multi*(-pow(cycle_r - polyg_inner_r, 2)),\n")
file.write("xyz(1,0,1): multi*2*h*(-2*polyg_inner_r + cycle_r),\n")
file.write("xyz(1,0,0): multi*2*h*h*polyg_inner_r,\n")
file.write("xyz(0,0,1): multi*2*h*polyg_inner_r*(polyg_inner_r - cycle_r),\n")
file.write("xyz(0,0,0): multi*(-pow(polyg_inner_r*h, 2))\n")
file.write("sturm\n")
file.write("}\n\n")
file.write("#local mockup1 =\n")
file.write("difference{\n")
file.write(" cylinder{\n")
file.write(" <0,0,0.0>,<0,0,h>, max(polyg_outer_r, cycle_r)\n")
file.write(" }\n\n")
file.write(" #for(i, 0, n-1)\n")
file.write(" object{\n")
file.write(" poly_obj\n")
file.write(" inverse\n")
file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
file.write(" }\n")
file.write(" object{\n")
file.write(" Shape_Slice_Plane_2P_1V(<polyg_inner_r,0,0>,<cycle_r,0,h>,x)\n")
file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
file.write(" }\n")
file.write(" #end\n")
file.write("}\n\n")
file.write("object{\n")
file.write("mockup1\n")
file.write("rotate <0, 0, degrees(face_ang)>\n")
file.write("}\n")
file.write("#end\n")
#Use the macro
ngon = ob.pov.polytocircle_ngon
ngonR = ob.pov.polytocircle_ngonR
circleR = ob.pov.polytocircle_circleR
tabWrite("#declare %s = object { Shape_Polygon_To_Circle_Blending(%s, z, %.4f, %.4f, 2) rotate x*180 translate z*1\n"%(povdataname,ngon,ngonR,circleR))
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
############################################else try to export mesh
elif ob.is_instancer == False: #except duplis which should be instances groups for now but all duplis later
Maurice Raybaud
committed
if ob.type == 'EMPTY':
tabWrite("\n//dummy sphere to represent Empty location\n")
tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
# TODO(sergey): PovRay is a render engine, so should be using dependency graph
# which was given to it via render engine API.
depsgraph = bpy.context.evaluated_depsgraph_get()
ob_eval = ob.evaluated_get(depsgraph)
#XXX Here? identify the specific exception for mesh object with no data
#XXX So that we can write something for the dataname !
# also happens when curves cant be made into meshes because of no-data
continue
importance = ob.pov.importance_value
me_materials = me.materials
Maurice Raybaud
committed
#if len(me_faces)==0:
#tabWrite("\n//dummy sphere to represent empty mesh location\n")
#tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
if not me or not me_faces:
Maurice Raybaud
committed
tabWrite("\n//dummy sphere to represent empty mesh location\n")
tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
uv_layers = me.uv_layers
if len(uv_layers) > 0:
if me.uv_layers.active and uv_layers.active.data:
uv_layer = uv_layers.active.data
uv_layer = None
try:
#vcol_layer = me.vertex_colors.active.data
vcol_layer = me.vertex_colors.active.data
except AttributeError:
vcol_layer = None
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]
# Use named declaration to allow reference e.g. for baking. MR
file.write("\n")
tabWrite("#declare %s =\n" % povdataname)
tabWrite("mesh2 {\n")
tabWrite("vertex_vectors {\n")
tabWrite("%d" % len(me.vertices)) # vert count
tabStr = tab * tabLevel
for v in me.vertices:
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
file.write(", ")
file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
#tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
file.write("\n")
tabWrite("}\n")
# Build unique Normal list
uniqueNormals = {}
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]
else: # Use face normal
key = faces_normals[fi]
uniqueNormals[key] = [-1]
tabWrite("normal_vectors {\n")
tabWrite("%d" % len(uniqueNormals)) # vert count
idx = 0
tabStr = tab * tabLevel
for no, index in uniqueNormals.items():
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count
file.write("<%.6f, %.6f, %.6f>" % no) # vert count
index[0] = idx
idx += 1
file.write("\n")
tabWrite("}\n")
# Vertex colors
vertCols = {} # Use for material colors also.
if uv_layer:
# Generate unique UV's
uniqueUVs = {}
#n = 0
uvs = [uv_layer[l].uv[:] for l in f.loops]
for uv in uvs:
uniqueUVs[uv[:]] = [-1]
tabWrite("uv_vectors {\n")
#print unique_uvs
tabWrite("%d" % len(uniqueUVs)) # vert count
idx = 0
tabStr = tab * tabLevel
for uv, index in uniqueUVs.items():
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f>" % uv)
file.write(", ")
file.write("<%.6f, %.6f>" % uv)
index[0] = idx
idx += 1
'''
# Just add 1 dummy vector, no real UV's
tabWrite('1') # vert count
file.write(',\n\t\t<0.0, 0.0>')
'''
file.write("\n")
tabWrite("}\n")
if me.vertex_colors:
#Write down vertex colors as a texture for each vertex
tabWrite("texture_list {\n")
tabWrite("%d\n" % (len(me_faces) * 3)) # assumes we have only triangles
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
material_index = f.material_index
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
cols = [vcol_layer[l].color[:] for l in f.loops]
for col in cols:
key = col[0], col[1], col[2], material_index # Material index!
VcolIdx+=1
vertCols[key] = [VcolIdx]
if linebreaksinlists:
Maurice Raybaud
committed
tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2]))
Maurice Raybaud
committed
tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2]))
tabStr = tab * tabLevel
else:
if material:
# Multiply diffuse with SSS Color
if material.pov_subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])]
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]
# Face indices
tabWrite("\nface_indices {\n")
tabWrite("%d" % (len(me_faces))) # faces count
tabStr = tab * tabLevel
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
material_index = f.material_index
cols = [vcol_layer[l].color[:] for l in f.loops]
if not me_materials or me_materials[material_index] is None: # No materials
if linebreaksinlists:
file.write(",\n")
# vert count
file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count
material = me_materials[material_index]
if me.vertex_colors: #and material.use_vertex_color_paint:
# Color per vertex - vertex color
col1 = cols[0]
col2 = cols[1]
col3 = cols[2]
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.pov_subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])]
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
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
(fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>, %d,%d,%d" % \
(fv[0], fv[1], fv[2], 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))) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if me_faces[fi].use_smooth:
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[0]]][0],\
uniqueNormals[verts_normals[fv[1]]][0],\
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[0]]][0],\
uniqueNormals[verts_normals[fv[1]]][0],\
uniqueNormals[verts_normals[fv[2]]][0])) # vert count
idx = uniqueNormals[faces_normals[fi]][0]
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count
Maurice Raybaud
committed
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))) # faces count
tabStr = tab * tabLevel
for f in me_faces:
uvs = [uv_layer[l].uv[:] for l in f.loops]
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (
uniqueUVs[uvs[0]][0],\
uniqueUVs[uvs[1]][0],\
uniqueUVs[uvs[2]][0]))
Maurice Raybaud
committed
else:
file.write(", ")
file.write("<%d,%d,%d>" % (
uniqueUVs[uvs[0]][0],\
uniqueUVs[uvs[1]][0],\
uniqueUVs[uvs[2]][0]))
file.write("\n")
tabWrite("}\n")
#XXX BOOLEAN
onceCSG = 0
for mod in ob.modifiers:
if onceCSG == 0:
if mod :
if mod.type == 'BOOLEAN':
if ob.pov.boolean_mod == "POV":
file.write("\tinside_vector <%.6g, %.6g, %.6g>\n" %
(ob.pov.inside_vector[0],
ob.pov.inside_vector[1],
ob.pov.inside_vector[2]))
onceCSG = 1
if me.materials:
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
# hollow / sturm / double_illuminate etc.
Maurice Raybaud
committed
#Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of mesh block
else:
facesMaterials = [] # WARNING!!!!!!!!!!!!!!!!!!!!!!
if me_materials:
for f in me_faces:
if f.material_index not in facesMaterials:
facesMaterials.append(f.material_index)
# No vertex colors, so write material colors as vertex colors
for i, material in enumerate(me_materials):
if material and material.pov.material_use_nodes == False: # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Multiply diffuse with SSS Color
if material.pov_subsurface_scattering.use: