Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2012-10-02 01:43:44 +0400
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2012-10-02 01:43:44 +0400
commite55581d1ed282960be6755261f14f0b218fdb669 (patch)
tree92961833d9b3066246388bca5cc2ab67562ecb99
parentdece894f25c81b623fafbb9f2456910394fab6c9 (diff)
First try at hair particles support.
-rw-r--r--render_povray/__init__.py1
-rw-r--r--render_povray/render.py145
-rw-r--r--render_povray/ui.py9
3 files changed, 149 insertions, 6 deletions
diff --git a/render_povray/__init__.py b/render_povray/__init__.py
index b4843919..1b7299ec 100644
--- a/render_povray/__init__.py
+++ b/render_povray/__init__.py
@@ -45,6 +45,7 @@ else:
from . import ui
from . import render
from . import update_files
+
###############################################################################
diff --git a/render_povray/render.py b/render_povray/render.py
index a009c9d5..8b895907 100644
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -1,4 +1,4 @@
- # ***** BEGIN GPL LICENSE BLOCK *****
+ # ***** 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
@@ -751,7 +751,7 @@ def write_pov(filename, scene=None, info_callback=None):
# for ms in ob.material_slots:
# if ms.material != None and ms.link == 'OBJECT':
# # If there is at least one material slot linked to the object
-# # and not the data (mesh), always create a new, “private” data instance.
+# # and not the data (mesh), always create a new, private data instance.
# return True
# return False
# For objects using local material(s) only!
@@ -790,7 +790,7 @@ def write_pov(filename, scene=None, info_callback=None):
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.
- # This func returns the “povray” name of the data, or None
+ # This func returns the povray name of the data, or None
# if no writing is needed.
if ob.is_modified(scene, 'RENDER'):
# Data modified.
@@ -816,9 +816,142 @@ def write_pov(filename, scene=None, info_callback=None):
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!
+ # for object we wont export here!
if ob.type in {'LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'}:
continue
+
+ # Export Hair
+
+ if hasattr(ob, 'particle_systems') != False:
+ for pSys in ob.particle_systems:
+ if not pSys.settings.use_render_emitter:
+ continue #don't render mesh
+ 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:
+ pmaterial = ob.active_material
+ 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
+ strandEnd = pmaterial.strand.tip_size / 200
+ strandShape = pmaterial.strand.shape
+ else:
+ pmaterial = "default" # No material assigned in blender, use default one
+ strandStart = 0.01
+ strandEnd = 0.01
+ strandShape = 0.0
+
+ totalNumberOfHairs = len(pSys.particles)
+ hairCounter = 0
+ file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs)
+ for particle in pSys.particles:
+ 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' % (len(particle.hair_keys) + 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' % (len(particle.hair_keys)))
+ for controlPoint in particle.hair_keys:
+ if pSys.settings.clump_factor != 0:
+ hDiameter = pSys.settings.clump_factor #* random.uniform(0.5, 1)
+ elif controlPointCounter == 0:
+ hDiameter = strandStart
+ else:
+ hDiameter += (strandEnd-strandStart)/(len(particle.hair_keys)+1) #XXX +1 or not?
+ if controlPointCounter == 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' % (controlPoint.co[0], controlPoint.co[1], controlPoint.co[2], abs(hDiameter)))
+ file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (controlPoint.co[0], controlPoint.co[1], controlPoint.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' % (controlPoint.co[0], controlPoint.co[1], controlPoint.co[2], abs(hDiameter)))
+
+ # All coordinates except the last need a following comma.
+
+ if controlPointCounter != len(particle.hair_keys):
+ file.write(',\n')
+ else:
+ # 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 hairCounter != totalNumberOfHairs:
+ file.write(',\n')
+ else:
+ file.write('\n')
+
+ # End the array declaration.
+
+ file.write('}\n')
+ file.write('\n')
+
+ # Pick up the hair 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 hairs (or a subset of the hairs).
+ # By default use every 25th hair, which is usually ok for test renders.
+
+ file.write('#ifndef(HairStep) #declare HairStep = %d; #end\n' % ((totalNumberOfHairs/(totalNumberOfHairs * pSys.settings.draw_percentage / 100))))
+ file.write('union{\n')
+ file.write(' #local I = 0;\n')
+ file.write(' #while (I < %i)\n' % totalNumberOfHairs)
+ file.write(' object {HairArray[I] texture{HairTexture}\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 {\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))
+
+
try:
me = ob.to_mesh(scene, True, 'RENDER')
@@ -829,14 +962,14 @@ def write_pov(filename, scene=None, info_callback=None):
importance = ob.pov.importance_value
me_materials = me.materials
me_faces = me.tessfaces[:]
-
+
if not me or not me_faces:
continue
#############################################
# 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,
+ # XXX I dont understand that if we are here, sel if a non-empty iterable,
# so this condition is always True, IMO -- mont29
if sel:
name_orig = "OB" + ob.name
diff --git a/render_povray/ui.py b/render_povray/ui.py
index 0fa91a2b..0af5253e 100644
--- a/render_povray/ui.py
+++ b/render_povray/ui.py
@@ -83,6 +83,15 @@ for member in dir(properties_data_lamp):
pass
del properties_data_lamp
+from bl_ui import properties_particle as properties_particle
+for member in dir(properties_particle): # add all "particle" panels from blender
+ subclass = getattr(properties_particle, member)
+ try:
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
+ except:
+ pass
+del properties_particle
+
class RenderButtonsPanel():
bl_space_type = 'PROPERTIES'