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
#subtract original from the count of their instances as were not counted before 2.8
if not (ob.is_instancer and ob.original != ob):
ob_num += 1
# XXX I moved all those checks here, as there is no need to compute names
# for object we won't export here!
if (ob.type in {'LIGHT', 'CAMERA', #'EMPTY', #empties can bear dupligroups
'META', 'ARMATURE', 'LATTICE'}):
continue
smokeFlag=False
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.
if not smokeFlag:
# Export Hair
renderEmitter = True
if hasattr(ob, 'particle_systems'):
renderEmitter = False
if ob.show_instancer_for_render:
renderEmitter = True
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
for pSys in ob.particle_systems:
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
strandShape = pmaterial.strand.shape
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
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
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]
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]))
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)
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:
# End the array declaration.
2205
2206
2207
2208
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
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
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 {srgbt <%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')
# 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 {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)
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
if ob.data:
Maurice Raybaud
committed
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.data.name
elif ob.is_instancer:
if ob.instance_type == 'COLLECTION':
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.instance_collection.name
else:
#hoping only dupligroups have several source datablocks
#ob_dupli_list_create(scene) #deprecated in 2.8
depsgraph = bpy.context.evaluated_depsgraph_get()
for eachduplicate in depsgraph.object_instances:
if eachduplicate.is_instance: # Real dupli instance filtered because original included in list since 2.8
dataname_orig = "DATA" + eachduplicate.object.name
#ob.dupli_list_clear() #just don't store any reference to instance since 2.8
elif ob.type == 'EMPTY':
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.name
Maurice Raybaud
committed
else:
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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)
continue
2311
2312
2313
2314
2315
2316
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
2363
2364
2365
2366
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
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
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
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
2418
2419
2420
2421
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:
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 == '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
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
if ob.pov.object_as == 'CYLINDER':
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)
#cylinders written at origin, translated below
write_object_modifiers(scene,ob,file)
#tabWrite("rotate x*90\n")
tabWrite("}\n")
continue #Don't render proxy mesh, skip to next object
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
2530
2531
2532
2533
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
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
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
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
2672
2673
2674
2675
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")
else:
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
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
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)
try:
me = ob_eval.to_mesh()
#XXX Here? identify the specific exception for mesh object with no data
#XXX So that we can write something for the dataname !
except:
# also happens when curves cant be made into meshes because of no-data
continue
importance = ob.pov.importance_value
if me:
me.calc_loop_triangles()
me_materials = me.materials
me_faces = me.loop_triangles[:]
#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:
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)
continue
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
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
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
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(", ")
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
for f in me_faces: # me.faces in 2.7
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("<%.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")
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
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:
tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2]))
else:
tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2]))
tabStr = tab * tabLevel
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]
tabWrite("\n}\n")
# 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
if vcol_layer:
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
Maurice Raybaud
committed
else:
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]
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
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[:])]
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
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
Maurice Raybaud
committed
else:
idx = uniqueNormals[faces_normals[fi]][0]
if linebreaksinlists:
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))) # 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]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (
uniqueUVs[uvs[0]][0],\
uniqueUVs[uvs[1]][0],\
uniqueUVs[uvs[2]][0]))
Maurice Raybaud
committed
file.write("\n")
tabWrite("}\n")
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
#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)
# POV object modifiers such as
# hollow / sturm / double_illuminate etc.
write_object_modifiers(scene,ob,file)
#Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
Maurice Raybaud
committed
tabWrite("}\n") # End of mesh block
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):