diff options
author | Maurice Raybaud <mauriceraybaud@hotmail.fr> | 2015-11-12 17:57:29 +0300 |
---|---|---|
committer | Maurice Raybaud <mauriceraybaud@hotmail.fr> | 2015-11-12 17:57:29 +0300 |
commit | 8e88b29ff93b1cab5c8fa1822297d60b23b81dae (patch) | |
tree | f4443758e99bbfc58e873f2e5a52dbd24a8d3a96 /render_povray | |
parent | 2391d5041b3ff02967d487611b6c1afafc211e8e (diff) |
*Added POV-Ray Primitives, available in ADD menu
*Added Import Menu using PovSphere primitive to import pov files output from Avogadro
*Added editable properties and update for pov objects
Diffstat (limited to 'render_povray')
-rw-r--r-- | render_povray/__init__.py | 640 | ||||
-rw-r--r-- | render_povray/render.py | 4604 | ||||
-rw-r--r-- | render_povray/ui.py | 617 |
3 files changed, 4854 insertions, 1007 deletions
diff --git a/render_povray/__init__.py b/render_povray/__init__.py index bd68f5e9..74ab9795 100644 --- a/render_povray/__init__.py +++ b/render_povray/__init__.py @@ -20,9 +20,10 @@ bl_info = { "name": "POV-Ray 3.7", - "author": "Campbell Barton, Silvio Falcinelli, Maurice Raybaud, Constantin Rahn, Bastien Montagne", + "author": "Campbell Barton, Silvio Falcinelli, Maurice Raybaud, " + "Constantin Rahn, Bastien Montagne, Leonid Desyatkov", "version": (0, 0, 9), - "blender": (2, 57, 0), + "blender": (2, 75, 0), "location": "Render > Engine > POV-Ray 3.7", "description": "Basic POV-Ray 3.7 integration for blender", "warning": "this script is RC", @@ -39,6 +40,7 @@ if "bpy" in locals(): else: import bpy + import addon_utils # To use some other addons from bpy.types import ( AddonPreferences, PropertyGroup, @@ -52,6 +54,7 @@ else: FloatVectorProperty, EnumProperty, PointerProperty, + CollectionProperty, ) from . import ( ui, @@ -59,6 +62,7 @@ else: update_files, ) + def string_strip_hyphen(name): return name.replace("-", "") @@ -69,34 +73,40 @@ class RenderPovSettingsScene(PropertyGroup): # File Options tempfiles_enable = BoolProperty( name="Enable Tempfiles", - description="Enable the OS-Tempfiles. Otherwise set the path where to save the files", + description="Enable the OS-Tempfiles. Otherwise set the path where" + " to save the files", default=True) pov_editor = BoolProperty( name="POV-Ray editor", - description="Don't Close POV-Ray editor after rendering (Overriden by /EXIT command)", + description="Don't Close POV-Ray editor after rendering (Overriden" + " by /EXIT command)", default=False) deletefiles_enable = BoolProperty( name="Delete files", - description="Delete files after rendering. Doesn't work with the image", + description="Delete files after rendering. " + "Doesn't work with the image", default=True) scene_name = StringProperty( name="Scene Name", - description="Name of POV-Ray scene to create. Empty name will use the name of " - "the blend file", + description="Name of POV-Ray scene to create. Empty name will use " + "the name of the blend file", maxlen=1024) scene_path = StringProperty( name="Export scene path", - # description="Path to directory where the exported scene (POV and INI) is created", # Bug in POV-Ray RC3 + # Bug in POV-Ray RC3 + # description="Path to directory where the exported scene " + # "(POV and INI) is created", description="Path to directory where the files are created", maxlen=1024, subtype="DIR_PATH") renderimage_path = StringProperty( name="Rendered image path", - description="Full path to directory where the rendered image is saved", + description="Full path to directory where the rendered image is " + "saved", maxlen=1024, subtype="DIR_PATH") list_lf_enable = BoolProperty( name="LF in lists", - description="Enable line breaks in lists (vectors and indices). Disabled: " - "lists are exported in one line", + description="Enable line breaks in lists (vectors and indices). " + "Disabled: lists are exported in one line", default=True) # Not a real pov option, just to know if we should write @@ -104,10 +114,12 @@ class RenderPovSettingsScene(PropertyGroup): name="Enable Radiosity", description="Enable POV-Rays radiosity calculation", default=False) + radio_display_advanced = BoolProperty( name="Advanced Options", description="Show advanced options", default=False) + media_enable = BoolProperty( name="Enable Media", description="Enable POV-Rays atmospheric media", @@ -121,7 +133,9 @@ class RenderPovSettingsScene(PropertyGroup): media_color = FloatVectorProperty( name="Media Color", description="The atmospheric media color", precision=4, step=0.01, min=0, soft_max=1, - default=(0.001, 0.001, 0.001), options={'ANIMATABLE'}, subtype='COLOR') + default=(0.001, 0.001, 0.001), + options={'ANIMATABLE'}, + subtype='COLOR') baking_enable = BoolProperty( name="Enable Baking", @@ -147,8 +161,9 @@ class RenderPovSettingsScene(PropertyGroup): # Real pov options command_line_switches = StringProperty( name="Command Line Switches", - description="Command line switches consist of a + (plus) or - (minus) sign, followed " - "by one or more alphabetic characters and possibly a numeric value", + description="Command line switches consist of a + (plus) or - " + "(minus) sign, followed by one or more alphabetic " + "characters and possibly a numeric value", maxlen=500) antialias_enable = BoolProperty( @@ -157,13 +172,15 @@ class RenderPovSettingsScene(PropertyGroup): antialias_method = EnumProperty( name="Method", - description="AA-sampling method. Type 1 is an adaptive, non-recursive, super-sampling " - "method. Type 2 is an adaptive and recursive super-sampling method. " - "Type 3 is a stochastic halton based super-sampling method", + description="AA-sampling method. Type 1 is an adaptive, " + "non-recursive, super-sampling method. Type 2 is an " + "adaptive and recursive super-sampling method. Type 3 " + "is a stochastic halton based super-sampling method", items=(("0", "non-recursive AA", "Type 1 Sampling in POV-Ray"), ("1", "recursive AA", "Type 2 Sampling in POV-Ray"), ("2", "stochastic AA", "Type 3 Sampling in UberPOV")), default="1") + antialias_confidence = FloatProperty( name="Antialias Confidence", description="how surely the computed color " @@ -180,8 +197,9 @@ class RenderPovSettingsScene(PropertyGroup): jitter_enable = BoolProperty( name="Jitter", - description="Enable Jittering. Adds noise into the sampling process (it should be " - "avoided to use jitter in animation)", + description="Enable Jittering. Adds noise into the sampling " + "process (it should be avoided to use jitter in " + "animation)", default=False) jitter_amount = FloatProperty( @@ -190,34 +208,56 @@ class RenderPovSettingsScene(PropertyGroup): antialias_gamma = FloatProperty( name="Antialias Gamma", - description="POV-Ray compares gamma-adjusted values for super sampling. Antialias " - "Gamma sets the Gamma before comparison", + description="POV-Ray compares gamma-adjusted values for super " + "sampling. Antialias Gamma sets the Gamma before " + "comparison", min=0.0, max=5.0, soft_min=0.01, soft_max=2.5, default=2.5) max_trace_level = IntProperty( name="Max Trace Level", - description="Number of reflections/refractions allowed on ray path", + description="Number of reflections/refractions allowed on ray " + "path", min=1, max=256, default=5) + ########################### PHOTONS ####################################### + photon_enable = BoolProperty( + name="Photons", + description="Enable global photons", + default=False) + + photon_enable_count = BoolProperty( + name="Spacing / Count", + description="Enable count photons", + default=False) + + photon_count = IntProperty( + name="Count", + description="Photons count", + min=1, max=100000000, default=20000) + photon_spacing = FloatProperty( name="Spacing", - description="Average distance between photons on surfaces. half this get four times " - "as many surface photons", - min=0.001, max=1.000, soft_min=0.001, soft_max=1.000, default=0.005, precision=3) + description="Average distance between photons on surfaces. half " + "this get four times as many surface photons", + min=0.001, max=1.000, default=0.005, + soft_min=0.001, soft_max=1.000, precision=3) photon_max_trace_level = IntProperty( name="Max Trace Level", - description="Number of reflections/refractions allowed on ray path", + description="Number of reflections/refractions allowed on ray " + "path", min=1, max=256, default=5) photon_adc_bailout = FloatProperty( name="ADC Bailout", description="The adc_bailout for photons. Use adc_bailout = " "0.01 / brightest_ambient_object for good results", - min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default=0.1, precision=3) + min=0.0, max=1000.0, default=0.1, + soft_min=0.0, soft_max=1.0, precision=3) photon_gather_min = IntProperty( - name="Gather Min", description="Minimum number of photons gathered for each point", + name="Gather Min", description="Minimum number of photons gathered" + "for each point", min=1, max=256, default=20) photon_gather_max = IntProperty( @@ -228,7 +268,7 @@ class RenderPovSettingsScene(PropertyGroup): name="ADC Bailout", description="The adc_bailout for radiosity rays. Use " "adc_bailout = 0.01 / brightest_ambient_object for good results", - min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default=0.01, precision=3) + min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default=0.0039, precision=4) radio_always_sample = BoolProperty( name="Always Sample", @@ -291,7 +331,7 @@ class RenderPovSettingsScene(PropertyGroup): name="Recursion Limit", description="how many recursion levels are used to calculate " "the diffuse inter-reflection", - min=1, max=20, default=3) + min=1, max=20, default=1) radio_pretrace_start = FloatProperty( name="Pretrace Start", @@ -303,7 +343,7 @@ class RenderPovSettingsScene(PropertyGroup): name="Pretrace End", description="Fraction of the screen width which sets the size of the blocks " "in the mosaic preview last pass", - min=0.001, max=1.00, soft_min=0.01, soft_max=1.00, default=0.04, precision=3) + min=0.000925, max=1.00, soft_min=0.01, soft_max=1.00, default=0.04, precision=3) ############################################################################### @@ -352,7 +392,8 @@ class RenderPovSettingsMaterial(PropertyGroup): min=0.0, max=10.0, soft_min=0.000, soft_max=1.0, default=0) interior_fade_color = FloatVectorProperty( - name="Fade Color", description="Color of filtered attenuation for transparent materials", + name="Fade Color", description="Color of filtered attenuation for transparent " + "materials", precision=4, step=0.01, min=0.0, soft_max=1.0, default=(0, 0, 0), options={'ANIMATABLE'}, subtype='COLOR') @@ -439,29 +480,44 @@ class RenderPovSettingsTexture(PropertyGroup): tex_pattern_type = EnumProperty( name="Texture_Type", description="Choose between Blender or POV-Ray parameters to specify texture", - items= (('agate', 'Agate', '','PLUGIN', 0), ('aoi', 'Aoi', '', 'PLUGIN', 1), - ('average', 'Average', '', 'PLUGIN', 2), ('boxed', 'Boxed', '', 'PLUGIN', 3), - ('bozo', 'Bozo', '', 'PLUGIN', 4), ('bumps', 'Bumps', '', 'PLUGIN', 5), - ('cells', 'Cells', '', 'PLUGIN', 6), ('crackle', 'Crackle', '', 'PLUGIN', 7), - ('cubic', 'Cubic', '', 'PLUGIN', 8), ('cylindrical', 'Cylindrical', '', 'PLUGIN', 9), + items= (('agate', 'Agate', '','PLUGIN', 0), + ('aoi', 'Aoi', '', 'PLUGIN', 1), + ('average', 'Average', '', 'PLUGIN', 2), + ('boxed', 'Boxed', '', 'PLUGIN', 3), + ('bozo', 'Bozo', '', 'PLUGIN', 4), + ('bumps', 'Bumps', '', 'PLUGIN', 5), + ('cells', 'Cells', '', 'PLUGIN', 6), + ('crackle', 'Crackle', '', 'PLUGIN', 7), + ('cubic', 'Cubic', '', 'PLUGIN', 8), + ('cylindrical', 'Cylindrical', '', 'PLUGIN', 9), ('density_file', 'Density', '(.df3)', 'PLUGIN', 10), ('dents', 'Dents', '', 'PLUGIN', 11), ('fractal', 'Fractal', '', 'PLUGIN', 12), ('function', 'Function', '', 'PLUGIN', 13), - ('gradient', 'Gradient', '', 'PLUGIN', 14), ('granite', 'Granite', '', 'PLUGIN', 15), + ('gradient', 'Gradient', '', 'PLUGIN', 14), + ('granite', 'Granite', '', 'PLUGIN', 15), ('image_pattern', 'Image pattern', '', 'PLUGIN', 16), ('leopard', 'Leopard', '', 'PLUGIN', 17), - ('marble', 'Marble', '', 'PLUGIN', 18), ('onion', 'Onion', '', 'PLUGIN', 19), + ('marble', 'Marble', '', 'PLUGIN', 18), + ('onion', 'Onion', '', 'PLUGIN', 19), ('pigment_pattern', 'pigment pattern', '', 'PLUGIN', 20), - ('planar', 'Planar', '', 'PLUGIN', 21), ('quilted', 'Quilted', '', 'PLUGIN', 22), - ('radial', 'Radial', '', 'PLUGIN', 23), ('ripples', 'Ripples', '', 'PLUGIN', 24), + ('planar', 'Planar', '', 'PLUGIN', 21), + ('quilted', 'Quilted', '', 'PLUGIN', 22), + ('radial', 'Radial', '', 'PLUGIN', 23), + ('ripples', 'Ripples', '', 'PLUGIN', 24), ('slope', 'Slope', '', 'PLUGIN', 25), - ('spherical', 'Spherical', '', 'PLUGIN', 26), ('spiral1', 'Spiral1', '', 'PLUGIN', 27), - ('spiral2', 'Spiral2', '', 'PLUGIN', 28), ('spotted', 'Spotted', '', 'PLUGIN', 29), - ('waves', 'Waves', '', 'PLUGIN', 30), ('wood', 'Wood', '', 'PLUGIN', 31), - ('wrinkles', 'Wrinkles', '', 'PLUGIN', 32), ('brick', "Brick", "", 'PLUGIN', 33), - ('checker', "Checker", "", 'PLUGIN', 34), ('hexagon', "Hexagon", "", 'PLUGIN', 35), - ('object', "Mesh", "", 'PLUGIN', 36), ('emulator', "Internal Emulator", "", 'PLUG', 37)), + ('spherical', 'Spherical', '', 'PLUGIN', 26), + ('spiral1', 'Spiral1', '', 'PLUGIN', 27), + ('spiral2', 'Spiral2', '', 'PLUGIN', 28), + ('spotted', 'Spotted', '', 'PLUGIN', 29), + ('waves', 'Waves', '', 'PLUGIN', 30), + ('wood', 'Wood', '', 'PLUGIN', 31), + ('wrinkles', 'Wrinkles', '', 'PLUGIN', 32), + ('brick', "Brick", "", 'PLUGIN', 33), + ('checker', "Checker", "", 'PLUGIN', 34), + ('hexagon', "Hexagon", "", 'PLUGIN', 35), + ('object', "Mesh", "", 'PLUGIN', 36), + ('emulator', "Internal Emulator", "", 'PLUG', 37)), default='emulator', ) @@ -479,8 +535,9 @@ class RenderPovSettingsTexture(PropertyGroup): warp_types = EnumProperty( name="Warp Types", description="Select the type of warp", - items=(('PLANAR', "Planar", ""), ('CUBIC', "Cubic", ""), ('SPHERICAL', "Spherical", ""), - ('TOROIDAL', "Toroidal", ""), ('CYLINDRICAL', "Cylindrical", ""),('NONE', "None", "No indentation")), + items=(('PLANAR', "Planar", ""), ('CUBIC', "Cubic", ""), + ('SPHERICAL', "Spherical", ""), ('TOROIDAL', "Toroidal", ""), + ('CYLINDRICAL', "Cylindrical", ""), ('NONE', "None", "No indentation")), default='NONE') warp_orientation = EnumProperty( @@ -492,8 +549,8 @@ class RenderPovSettingsTexture(PropertyGroup): wave_type = EnumProperty( name="Waves type", description="Select the type of waves", - items=(('ramp', "Ramp", ""), ('sine', "Sine", ""), ('scallop', "Scallop", ""), ('cubic', "Cubic", ""), - ('poly', "Poly", ""), ('triangle', 'Triangle', "")), + items=(('ramp', "Ramp", ""), ('sine', "Sine", ""), ('scallop', "Scallop", ""), + ('cubic', "Cubic", ""), ('poly', "Poly", ""), ('triangle', 'Triangle', "")), default='ramp') gen_noise = IntProperty( @@ -544,12 +601,14 @@ class RenderPovSettingsTexture(PropertyGroup): modifier_phase = FloatProperty( name="Phase", - description="The phase value causes the map entries to be shifted so that the map starts and ends at a different place", + description="The phase value causes the map entries to be shifted so that the map " + "starts and ends at a different place", min=0.0, max=2.0, default=0.0) modifier_frequency = FloatProperty( name="Frequency", - description="The frequency keyword adjusts the number of times that a color map repeats over one cycle of a pattern", + description="The frequency keyword adjusts the number of times that a color map " + "repeats over one cycle of a pattern", min=0.0, max=25.0, default=2.0) modifier_turbulence = FloatProperty( @@ -703,8 +762,8 @@ class RenderPovSettingsTexture(PropertyGroup): description="", min=0, max=4, default=0) - #########FUNCTIONS######################################################################################################################### - #########FUNCTIONS######################################################################################################################### + #########FUNCTIONS############################################################################# + #########FUNCTIONS############################################################################# func_list = EnumProperty( name="Functions", @@ -715,21 +774,27 @@ class RenderPovSettingsTexture(PropertyGroup): ("f_bicorn","Bicorn",""), ("f_bifolia","Bifolia",""), ("f_blob","Blob",""), ("f_blob2","Blob2",""), ("f_boy_surface","Boy surface",""), ("f_comma","Comma",""), - ("f_cross_ellipsoids","Cross ellipsoids",""), ("f_crossed_trough","Crossed trough",""), - ("f_cubic_saddle","Cubic saddle",""), ("f_cushion","Cushion",""), - ("f_devils_curve","Devils curve",""), ("f_devils_curve_2d","Devils curve 2d",""), + ("f_cross_ellipsoids","Cross ellipsoids",""), + ("f_crossed_trough","Crossed trough",""), ("f_cubic_saddle","Cubic saddle",""), + ("f_cushion","Cushion",""), ("f_devils_curve","Devils curve",""), + ("f_devils_curve_2d","Devils curve 2d",""), ("f_dupin_cyclid","Dupin cyclid",""), ("f_ellipsoid","Ellipsoid",""), ("f_enneper","Enneper",""), ("f_flange_cover","Flange cover",""), - ("f_folium_surface","Folium surface",""), ("f_folium_surface_2d","Folium surface 2d",""), - ("f_glob","Glob",""), ("f_heart","Heart",""), - ("f_helical_torus","Helical torus",""), ("f_helix1","Helix1",""), - ("f_helix2","Helix2",""), ("f_hex_x","Hex x",""), + ("f_folium_surface","Folium surface",""), + ("f_folium_surface_2d","Folium surface 2d",""), ("f_glob","Glob",""), + ("f_heart","Heart",""), ("f_helical_torus","Helical torus",""), + ("f_helix1","Helix1",""), ("f_helix2","Helix2",""), ("f_hex_x","Hex x",""), ("f_hex_y","Hex y",""), ("f_hetero_mf","Hetero mf",""), - ("f_hunt_surface","Hunt surface",""), ("f_hyperbolic_torus","Hyperbolic torus",""), - ("f_isect_ellipsoids","Isect ellipsoids",""), ("f_kampyle_of_eudoxus","Kampyle of eudoxus",""), - ("f_kampyle_of_eudoxus_2d","Kampyle of eudoxus 2d",""), ("f_klein_bottle","Klein bottle",""), - ("f_kummer_surface_v1","Kummer surface v1",""), ("f_kummer_surface_v2","Kummer surface v2",""), - ("f_lemniscate_of_gerono","Lemniscate of gerono",""), ("f_lemniscate_of_gerono_2d","Lemniscate of gerono 2d",""), + ("f_hunt_surface","Hunt surface",""), + ("f_hyperbolic_torus","Hyperbolic torus",""), + ("f_isect_ellipsoids","Isect ellipsoids",""), + ("f_kampyle_of_eudoxus","Kampyle of eudoxus",""), + ("f_kampyle_of_eudoxus_2d","Kampyle of eudoxus 2d",""), + ("f_klein_bottle","Klein bottle",""), + ("f_kummer_surface_v1","Kummer surface v1",""), + ("f_kummer_surface_v2","Kummer surface v2",""), + ("f_lemniscate_of_gerono","Lemniscate of gerono",""), + ("f_lemniscate_of_gerono_2d","Lemniscate of gerono 2d",""), ("f_mesh1","Mesh1",""), ("f_mitre","Mitre",""), ("f_nodal_cubic","Nodal cubic",""), ("f_noise3d","Noise3d",""), ("f_noise_generator","Noise generator",""), ("f_odd","Odd",""), @@ -738,7 +803,8 @@ class RenderPovSettingsTexture(PropertyGroup): ("f_pillow","Pillow",""), ("f_piriform","Piriform",""), ("f_piriform_2d","Piriform 2d",""), ("f_poly4","Poly4",""), ("f_polytubes","Polytubes",""), ("f_quantum","Quantum",""), - ("f_quartic_paraboloid","Quartic paraboloid",""), ("f_quartic_saddle","Quartic saddle",""), + ("f_quartic_paraboloid","Quartic paraboloid",""), + ("f_quartic_saddle","Quartic saddle",""), ("f_quartic_cylinder","Quartic cylinder",""), ("f_r","R",""), ("f_ridge","Ridge",""), ("f_ridged_mf","Ridged mf",""), ("f_rounded_box","Rounded box",""), ("f_sphere","Sphere",""), @@ -748,7 +814,8 @@ class RenderPovSettingsTexture(PropertyGroup): ("f_superellipsoid","Superellipsoid",""), ("f_th","Th",""), ("f_torus","Torus",""), ("f_torus2","Torus2",""), ("f_torus_gumdrop","Torus gumdrop",""), ("f_umbrella","Umbrella",""), - ("f_witch_of_agnesi","Witch of agnesi",""), ("f_witch_of_agnesi_2d","Witch of agnesi 2d","")), + ("f_witch_of_agnesi","Witch of agnesi",""), + ("f_witch_of_agnesi_2d","Witch of agnesi 2d","")), default='NONE') @@ -879,10 +946,13 @@ class RenderPovSettingsTexture(PropertyGroup): tex_scale_z = FloatProperty( name="Scale Z", description="", - min=0.0, max=10000.0, default=1.0) + min=0.0, max=10000.0, default=1.0) + + ############################################################################### # Object POV properties. ############################################################################### + class RenderPovSettingsObject(PropertyGroup): # Importance sampling importance_value = FloatProperty( @@ -916,7 +986,399 @@ class RenderPovSettingsObject(PropertyGroup): "it points at. Any POV shape expected e.g: isosurface {}", default="") + #############POV-Ray specific object properties.############################ + object_as = StringProperty(maxlen=1024) + + imported_loc = FloatVectorProperty( + name="Imported Pov location", + precision=6, + default=(0.0, 0.0, 0.0)) + + unlock_parameters = BoolProperty(name="Lock",default = False) + + curveshape = EnumProperty( + name="Povray Shape Type", + items=(("birail", "Birail", ""), + ("cairo", "Cairo", ""), + ("lathe", "Lathe", ""), + ("loft", "Loft", ""), + ("prism", "Prism", ""), + ("sphere_sweep", "Sphere Sweep", "")), + default="sphere_sweep") + + mesh_write_as = EnumProperty( + name="Mesh Write As", + items=(("blobgrid", "Blob Grid", ""), + ("grid", "Grid", ""), + ("mesh", "Mesh", "")), + default="mesh") + # shape_as_light = StringProperty(name="Light",maxlen=1024) + + # object_ior = FloatProperty( + # name="IOR", description="IOR", + # min=1.0, max=10.0,default=1.0) + # fake_caustics_power = FloatProperty( + # name="Power", description="Fake caustics power", + # min=0.0, max=10.0,default=0.0) + # target = BoolProperty(name="Target",description="",default=False) + # target_value = FloatProperty( + # name="Value", description="", + # min=0.0, max=1.0,default=1.0) + # refraction = BoolProperty(name="Refraction",description="",default=False) + # dispersion = BoolProperty(name="Dispersion",description="",default=False) + # dispersion_value = FloatProperty( + # name="Dispersion", description="Good values are 1.01 to 1.1. ", + # min=1.0, max=1.2,default=1.01) + # dispersion_samples = IntProperty(name="Samples",min=2, max=100,default=7) + # reflection = BoolProperty(name="Reflection",description="",default=False) + # pass_through = BoolProperty(name="Pass through",description="",default=False) + no_shadow = BoolProperty(name="No Shadow",default=False) + + no_image = BoolProperty(name="No Image",default=False) + + no_reflection = BoolProperty(name="No Reflection",default=False) + + no_radiosity = BoolProperty(name="No Radiosity",default=False) + + inverse = BoolProperty(name="Inverse",default=False) + + sturm = BoolProperty(name="Sturm",default=False) + + double_illuminate = BoolProperty(name="Double Illuminate",default=False) + + hierarchy = BoolProperty(name="Hierarchy",default=False) + + hollow = BoolProperty(name="Hollow",default=False) + + boundorclip = EnumProperty( + name="Boundorclip", + items=(("none", "None", ""), + ("bounded_by", "Bounded_by", ""), + ("clipped_by", "Clipped_by", "")), + default="none") + boundorclipob = StringProperty(maxlen=1024) + + addboundorclip = BoolProperty(description="",default=False) + + blob_threshold = FloatProperty(name="Threshold",min=0.00, max=10.0, default=0.6) + + cylinder_radius = FloatProperty(name="Cylinder R",min=0.00, max=10.0, default=0.04) + + + + blob_strength = FloatProperty(name="Strength",min=-10.00, max=10.0, default=1.00) + + res_u = IntProperty(name="U",min=100, max=1000, default=500) + + res_v = IntProperty(name="V",min=100, max=1000, default=500) + + contained_by = EnumProperty( + name="Contained by", + items=(("box", "Box", ""), + ("sphere", "Sphere", "")), + default="box") + + container_scale = FloatProperty(name="Container Scale",min=0.0, max=10.0, default=1.00) + + threshold = FloatProperty(name="Threshold",min=0.0, max=10.0, default=0.00) + + accuracy = FloatProperty(name="Accuracy",min=0.0001, max=0.1, default=0.001) + + max_gradient = FloatProperty(name="Max Gradient",min=0.0, max=100.0, default=5.0) + + all_intersections = BoolProperty(name="All Intersections",default=False) + + max_trace = IntProperty(name="Max Trace",min=1, max=100,default=1) + + + + def prop_update_sphere(self, context): + bpy.ops.pov.sphere_update() + sphere_radius = FloatProperty(name="Sphere radius",min=0.00, max=10.0, default=0.5, update=prop_update_sphere) + + + + def prop_update_cone(self, context): + bpy.ops.pov.cone_update() + + cone_base_radius = FloatProperty( + name = "Base radius", description = "The first radius of the cone", + default = 1.0, min = 0.01, max = 100.0, update=prop_update_cone) + cone_cap_radius = FloatProperty( + name = "Cap radius", description = "The second radius of the cone", + default = 0.3, min = 0.0, max = 100.0, update=prop_update_cone) + + cone_segments = IntProperty( + name = "Segments", description = "Radial segmentation of proxy mesh", + default = 16, min = 3, max = 265, update=prop_update_cone) + + cone_height = FloatProperty( + name = "Height", description = "Height of the cone", + default = 2.0, min = 0.01, max = 100.0, update=prop_update_cone) + cone_base_z = FloatProperty() + cone_cap_z = FloatProperty() + +###########Parametric + def prop_update_parametric(self, context): + bpy.ops.pov.parametric_update() + + u_min = FloatProperty(name = "U Min", + description = "", + default = 0.0, update=prop_update_parametric) + v_min = FloatProperty(name = "V Min", + description = "", + default = 0.0, update=prop_update_parametric) + u_max = FloatProperty(name = "U Max", + description = "", + default = 6.28, update=prop_update_parametric) + v_max = FloatProperty(name = "V Max", + description = "", + default = 12.57, update=prop_update_parametric) + x_eq = StringProperty( + maxlen=1024, default = "cos(v)*(1+cos(u))*sin(v/8)", update=prop_update_parametric) + y_eq = StringProperty( + maxlen=1024, default = "sin(u)*sin(v/8)+cos(v/8)*1.5", update=prop_update_parametric) + z_eq = StringProperty( + maxlen=1024, default = "sin(v)*(1+cos(u))*sin(v/8)", update=prop_update_parametric) + +###########Torus + + def prop_update_torus(self, context): + bpy.ops.pov.torus_update() + + torus_major_segments = IntProperty( + name = "Segments", description = "Radial segmentation of proxy mesh", + default = 48, min = 3, max = 720, update=prop_update_torus) + torus_minor_segments = IntProperty( + name = "Segments", description = "Cross-section segmentation of proxy mesh", + default = 12, min = 3, max = 720, update=prop_update_torus) + torus_major_radius = FloatProperty( + name="Major radius", + description="Major radius", + min=0.00, max=100.00, default=1.0, update=prop_update_torus) + torus_minor_radius = FloatProperty( + name="Minor radius", + description="Minor radius", + min=0.00, max=100.00, default=0.25, update=prop_update_torus) + + +###########Rainbow + arc_angle = FloatProperty(name = "Arc angle", + description = "The angle of the raynbow arc in degrees", + default = 360, min = 0.01, max = 360.0) + falloff_angle = FloatProperty(name = "Falloff angle", + description = "The angle after which rainbow dissolves into background", + default = 360, min = 0.0, max = 360) + +###########HeightFields + + quality = IntProperty(name = "Quality", + description = "", + default = 100, min = 1, max = 100) + + hf_filename = StringProperty(maxlen = 1024) + + hf_gamma = FloatProperty( + name="Gamma", + description="Gamma", + min=0.0001, max=20.0, default=1.0) + + hf_premultiplied = BoolProperty( + name="Premultiplied", + description="Premultiplied", + default=True) + + hf_smooth = BoolProperty( + name="Smooth", + description="Smooth", + default=False) + + hf_water = FloatProperty( + name="Water Level", + description="Wather Level", + min=0.00, max=1.00, default=0.0) + + hf_hierarchy = BoolProperty( + name="Hierarchy", + description="Height field hierarchy", + default=True) + +##############Superellipsoid + def prop_update_superellipsoid(self, context): + bpy.ops.pov.superellipsoid_update() + + se_param1 = FloatProperty( + name="Parameter 1", + description="", + min=0.00, max=10.0, default=0.04) + + se_param2 = FloatProperty( + name="Parameter 2", + description="", + min=0.00, max=10.0, default=0.04) + + se_u = IntProperty(name = "U-segments", + description = "radial segmentation", + default = 20, min = 4, max = 265, + update=prop_update_superellipsoid) + se_v = IntProperty(name = "V-segments", + description = "lateral segmentation", + default = 20, min = 4, max = 265, + update=prop_update_superellipsoid) + se_n1 = FloatProperty(name = "Ring manipulator", + description = "Manipulates the shape of the Ring", + default = 1.0, min = 0.01, max = 100.0, + update=prop_update_superellipsoid) + se_n2 = FloatProperty(name = "Cross manipulator", + description = "Manipulates the shape of the cross-section", + default = 1.0, min = 0.01, max = 100.0, + update=prop_update_superellipsoid) + se_edit = EnumProperty(items=[("NOTHING", "Nothing", ""), + ("NGONS", "N-Gons", ""), + ("TRIANGLES", "Triangles", "")], + name="Fill up and down", + description="", + default='TRIANGLES', + update=prop_update_superellipsoid) +#############Used for loft and Superellipsoid, etc. + curveshape = EnumProperty( + name="Povray Shape Type", + items=(("birail", "Birail", ""), + ("cairo", "Cairo", ""), + ("lathe", "Lathe", ""), + ("loft", "Loft", ""), + ("prism", "Prism", ""), + ("sphere_sweep", "Sphere Sweep", ""), + ("sor", "Surface of Revolution", "")), + default="sphere_sweep") + +#############Supertorus + def prop_update_supertorus(self, context): + bpy.ops.pov.supertorus_update() + + st_major_radius = FloatProperty( + name="Major radius", + description="Major radius", + min=0.00, max=100.00, default=1.0, + update=prop_update_supertorus) + + st_minor_radius = FloatProperty( + name="Minor radius", + description="Minor radius", + min=0.00, max=100.00, default=0.25, + update=prop_update_supertorus) + + st_ring = FloatProperty( + name="Ring", + description="Ring manipulator", + min=0.0001, max=100.00, default=1.00, + update=prop_update_supertorus) + + st_cross = FloatProperty( + name="Cross", + description="Cross manipulator", + min=0.0001, max=100.00, default=1.00, + update=prop_update_supertorus) + + st_accuracy = FloatProperty( + name="Accuracy", + description="Supertorus accuracy", + min=0.00001, max=1.00, default=0.001) + + st_max_gradient = FloatProperty( + name="Gradient", + description="Max gradient", + min=0.0001, max=100.00, default=10.00, + update=prop_update_supertorus) + + st_R = FloatProperty(name = "big radius", + description = "The radius inside the tube", + default = 1.0, min = 0.01, max = 100.0, + update=prop_update_supertorus) + st_r = FloatProperty(name = "small radius", + description = "The radius of the tube", + default = 0.3, min = 0.01, max = 100.0, + update=prop_update_supertorus) + st_u = IntProperty(name = "U-segments", + description = "radial segmentation", + default = 16, min = 3, max = 265, + update=prop_update_supertorus) + st_v = IntProperty(name = "V-segments", + description = "lateral segmentation", + default = 8, min = 3, max = 265, + update=prop_update_supertorus) + st_n1 = FloatProperty(name = "Ring manipulator", + description = "Manipulates the shape of the Ring", + default = 1.0, min = 0.01, max = 100.0, + update=prop_update_supertorus) + st_n2 = FloatProperty(name = "Cross manipulator", + description = "Manipulates the shape of the cross-section", + default = 1.0, min = 0.01, max = 100.0, + update=prop_update_supertorus) + st_ie = BoolProperty(name = "Use Int.+Ext. radii", + description = "Use internal and external radii", + default = False, + update=prop_update_supertorus) + st_edit = BoolProperty(name="", + description="", + default=False, + options={'HIDDEN'}, + update=prop_update_supertorus) + +########################Loft + loft_n = IntProperty(name = "Segments", + description = "Vertical segments", + default = 16, min = 3, max = 720) + loft_rings_bottom = IntProperty(name = "Bottom", + description = "Bottom rings", + default = 5, min = 2, max = 100) + loft_rings_side = IntProperty(name = "Side", + description = "Side rings", + default = 10, min = 2, max = 100) + loft_thick = FloatProperty(name = "Thickness", + description = "Manipulates the shape of the Ring", + default = 0.3, min = 0.01, max = 1.0) + loft_r = FloatProperty(name = "Radius", + description = "Radius", + default = 1, min = 0.01, max = 10) + loft_height = FloatProperty(name = "Height", + description = "Manipulates the shape of the Ring", + default = 2, min = 0.01, max = 10.0) + +###################Prism + prism_n = IntProperty(name = "Sides", + description = "Number of sides", + default = 5, min = 3, max = 720) + prism_r = FloatProperty(name = "Radius", + description = "Radius", + default = 1.0) + +##################Isosurface + iso_function_text = StringProperty(name="Function Text",maxlen=1024)#,update=iso_props_update_callback) + +##################PolygonToCircle + polytocircle_resolution = IntProperty(name = "Resolution", + description = "", + default = 3, min = 0, max = 256) + polytocircle_ngon = IntProperty(name = "NGon", + description = "", + min = 3, max = 64,default = 5) + polytocircle_ngonR = FloatProperty(name = "NGon Radius", + description = "", + default = 0.3) + polytocircle_circleR = FloatProperty(name = "Circle Radius", + description = "", + default = 1.0) + +#################Avogadro + # filename_ext = ".png" + + # filter_glob = StringProperty( + # default="*.exr;*.gif;*.hdr;*.iff;*.jpeg;*.jpg;*.pgm;*.png;*.pot;*.ppm;*.sys;*.tga;*.tiff;*.EXR;*.GIF;*.HDR;*.IFF;*.JPEG;*.JPG;*.PGM;*.PNG;*.POT;*.PPM;*.SYS;*.TGA;*.TIFF", + # options={'HIDDEN'}, + # ) + ############################################################################### # Camera POV properties. ############################################################################### @@ -965,6 +1427,7 @@ class RenderPovSettingsCamera(PropertyGroup): default="") + ############################################################################### # Text POV properties. ############################################################################### @@ -983,8 +1446,10 @@ class PovrayPreferences(AddonPreferences): branch_feature_set_povray = EnumProperty( name="Feature Set", - description="Choose between official (POV-Ray) or (UberPOV) development branch features to write in the pov file", - items= (('povray', 'Official POV-Ray', '','PLUGIN', 0), ('uberpov', 'Unofficial UberPOV', '', 'PLUGIN', 1)), + description="Choose between official (POV-Ray) or (UberPOV) " + "development branch features to write in the pov file", + items= (('povray', 'Official POV-Ray', '','PLUGIN', 0), + ('uberpov', 'Unofficial UberPOV', '', 'PLUGIN', 1)), default='povray' ) @@ -998,29 +1463,54 @@ class PovrayPreferences(AddonPreferences): layout.prop(self, "branch_feature_set_povray") layout.prop(self, "filepath_povray") - - + def register(): bpy.utils.register_module(__name__) + bpy.types.INFO_MT_add.prepend(ui.menu_func_add) + bpy.types.INFO_MT_file_import.append(ui.menu_func_import) + #used for parametric objects: + addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True) + #bpy.types.TEXTURE_PT_context_texture.prepend(TEXTURE_PT_povray_type) bpy.types.Scene.pov = PointerProperty(type=RenderPovSettingsScene) bpy.types.Material.pov = PointerProperty(type=RenderPovSettingsMaterial) bpy.types.Texture.pov = PointerProperty(type=RenderPovSettingsTexture) bpy.types.Object.pov = PointerProperty(type=RenderPovSettingsObject) + #bpy.types.Object.povsuperellipsoid = CollectionProperty(type=RenderPovSettingsSuperellipsoid_add) + #bpy.types.Object.povsupertorus = CollectionProperty(type=RenderPovSettingsSupertorus_add) + #bpy.types.Object.povloft = CollectionProperty(type=RenderPovSettingsLoft_add) + #bpy.types.Object.povrainbow = CollectionProperty(type=RenderPovSettingsRainbow_add) + #bpy.types.Object.povheightfield = CollectionProperty(type=RenderPovSettingsHeightField_add) + #bpy.types.Object.povtorus = CollectionProperty(type=RenderPovSettingsTorus_add) + #bpy.types.Object.povprism = CollectionProperty(type=RenderPovSettingsPrism_add) + #bpy.types.Object.povpolygontocircle = CollectionProperty(type=RenderPovSettingsPolygonToCircle_add) bpy.types.Camera.pov = PointerProperty(type=RenderPovSettingsCamera) bpy.types.Text.pov = PointerProperty(type=RenderPovSettingsText) + def unregister(): - bpy.utils.unregister_module(__name__) #bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_povray_type) del bpy.types.Scene.pov del bpy.types.Material.pov del bpy.types.Texture.pov del bpy.types.Object.pov + #del bpy.types.Object.povsuperellipsoid + #del bpy.types.Object.povsupertorus + #del bpy.types.Object.povloft + #del bpy.types.Object.povrainbow + #del bpy.types.Object.povheightfield + #del bpy.types.Object.povtorus + #del bpy.types.Object.povprism + #del bpy.types.Object.povpolygontocircle del bpy.types.Camera.pov del bpy.types.Text.pov + + addon_utils.disable("add_mesh_extra_objects", default_set=False) + bpy.types.INFO_MT_file_import.remove(ui.menu_func_import) + bpy.types.INFO_MT_add.remove(ui.menu_func_add) + bpy.utils.unregister_module(__name__) if __name__ == "__main__": diff --git a/render_povray/render.py b/render_povray/render.py index ae914265..90718e38 100644 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -23,12 +23,15 @@ import subprocess import os import sys import time -from math import atan, pi, degrees, sqrt +from math import atan, pi, degrees, sqrt, cos, sin import re import random import platform# import subprocess# -from bpy.types import(Operator)#all added for render preview +from bpy.types import(Operator) +from bpy_extras.io_utils import ImportHelper +from bpy_extras import object_utils + from . import df3 # for smoke rendering ##############################SF########################### ##############find image texture @@ -185,12 +188,131 @@ def renderable_objects(): tabLevel = 0 unpacked_images=[] -workDir = bpy.utils.resource_path('USER') +workDir = bpy.utils.resource_path('USER') +if not os.path.isdir(workDir): + os.mkdir(workDir) previewDir=os.path.join(workDir, "preview") ## Make sure Preview directory exists and is empty if not os.path.isdir(previewDir): os.mkdir(previewDir) smokePath = os.path.join(previewDir, "smoke.df3") + +def write_global_setting(scene,file): + file.write("global_settings {\n") + file.write(" assumed_gamma %.6f\n"%scene.pov.assumed_gamma) + if scene.pov.global_settings_default == False: + if scene.pov.adc_bailout_enable and scene.pov.radio_enable == False: + file.write(" adc_bailout %.6f\n"%scene.pov.adc_bailout) + if scene.pov.ambient_light_enable: + file.write(" ambient_light <%.6f,%.6f,%.6f>\n"%scene.pov.ambient_light[:]) + if scene.pov.irid_wavelength_enable: + file.write(" irid_wavelength <%.6f,%.6f,%.6f>\n"%scene.pov.irid_wavelength[:]) + if scene.pov.charset_enable: + file.write(" charset %s\n"%scene.pov.charset) + if scene.pov.max_trace_level_enable: + file.write(" max_trace_level %s\n"%scene.pov.max_trace_level) + if scene.pov.max_intersections_enable: + file.write(" max_intersections %s\n"%scene.pov.max_intersections) + if scene.pov.number_of_waves_enable: + file.write(" number_of_waves %s\n"%scene.pov.number_of_waves) + if scene.pov.noise_generator_enable: + file.write(" noise_generator %s\n"%scene.pov.noise_generator) + if scene.pov.sslt_enable: + file.write(" mm_per_unit %s\n"%scene.pov.mm_per_unit) + file.write(" subsurface {\n") + file.write(" samples %s, %s\n"%(scene.pov.sslt_samples_max,scene.pov.sslt_samples_min)) + if scene.pov.sslt_radiosity: + file.write(" radiosity on\n") + file.write("}\n") + + if scene.pov.radio_enable: + file.write(" radiosity {\n") + file.write(" pretrace_start %.6f\n"%scene.pov.radio_pretrace_start) + file.write(" pretrace_end %.6f\n"%scene.pov.radio_pretrace_end) + file.write(" count %s\n"%scene.pov.radio_count) + file.write(" nearest_count %s\n"%scene.pov.radio_nearest_count) + file.write(" error_bound %.6f\n"%scene.pov.radio_error_bound) + file.write(" recursion_limit %s\n"%scene.pov.radio_recursion_limit) + file.write(" low_error_factor %.6f\n"%scene.pov.radio_low_error_factor) + file.write(" gray_threshold %.6f\n"%scene.pov.radio_gray_threshold) + file.write(" maximum_reuse %.6f\n"%scene.pov.radio_maximum_reuse) + file.write(" minimum_reuse %.6f\n"%scene.pov.radio_minimum_reuse) + file.write(" brightness %.6f\n"%scene.pov.radio_brightness) + file.write(" adc_bailout %.6f\n"%scene.pov.radio_adc_bailout) + if scene.pov.radio_normal: + file.write(" normal on\n") + if scene.pov.radio_always_sample: + file.write(" always_sample on\n") + if scene.pov.radio_media: + file.write(" media on\n") + if scene.pov.radio_subsurface: + file.write(" subsurface on\n") + file.write(" }\n") + + if scene.pov.photon_enable: + file.write(" photons {\n") + if scene.pov.photon_enable_count: + file.write(" count %s\n"%scene.pov.photon_count) + else: + file.write(" spacing %.6g\n"%scene.pov.photon_spacing) + if scene.pov.photon_gather: + file.write(" gather %s, %s\n"%(scene.pov.photon_gather_min,scene.pov.photon_gather_max)) + if scene.pov.photon_autostop: + file.write(" autostop %.4g\n"%scene.pov.photon_autostop_value) + if scene.pov.photon_jitter_enable: + file.write(" jitter %.4g\n"%scene.pov.photon_jitter) + file.write(" max_trace_level %s\n"%scene.pov.photon_max_trace_level) + if scene.pov.photon_adc: + file.write(" adc_bailout %.6f\n"%scene.pov.photon_adc_bailout) + if scene.pov.photon_media_enable: + file.write(" media %s, %s\n"%(scene.pov.photon_media_steps,scene.pov.photon_media_factor)) + if scene.pov.photon_savefile or scene.pov.photon_loadfile: + filePh = bpy.path.abspath(scene.pov.photon_map_file) + if scene.pov.photon_savefile: + file.write('save_file "%s"\n'%filePh) + if scene.pov.photon_loadfile and os.path.exists(filePh): + file.write('load_file "%s"\n'%filePh) + file.write("}\n") + file.write("}\n") + +def write_object_modifiers(scene,ob,File): + if ob.pov.hollow: + File.write("hollow\n") + if ob.pov.double_illuminate: + File.write("double_illuminate\n") + if ob.pov.sturm: + File.write("sturm\n") + if ob.pov.no_shadow: + File.write("no_shadow\n") + if ob.pov.no_image: + File.write("no_image\n") + if ob.pov.no_reflection: + File.write("no_reflection\n") + if ob.pov.no_radiosity: + File.write("no_radiosity\n") + if ob.pov.inverse: + File.write("inverse\n") + if ob.pov.hierarchy: + File.write("hierarchy\n") + if scene.pov.photon_enable: + File.write("photons {\n") + if ob.pov.target: + File.write("target %.4g\n"%ob.pov.target_value) + if ob.pov.refraction: + File.write("refraction on\n") + if ob.pov.reflection: + File.write("reflection on\n") + if ob.pov.pass_through: + File.write("pass_through\n") + File.write("}\n") + # if ob.pov.object_ior > 1: + # File.write("interior {\n") + # File.write("ior %.4g\n"%ob.pov.object_ior) + # if scene.pov.photon_enable and ob.pov.target and ob.pov.refraction and ob.pov.dispersion: + # File.write("ior %.4g\n"%ob.pov.dispersion_value) + # File.write("ior %s\n"%ob.pov.dispersion_samples) + # if scene.pov.photon_enable == False: + # File.write("caustics %.4g\n"%ob.pov.fake_caustics_power) def exportPattern(texture): tex=texture @@ -1097,6 +1219,8 @@ def write_pov(filename, scene=None, info_callback=None): tabWrite("focal_point <0, 0, %f>\n" % focal_point) tabWrite("}\n") + + def exportLamps(lamps): # Incremented after each lamp export to declare its target # currently used for Fresnel diffuse shader as their slope vector: @@ -1189,7 +1313,823 @@ def write_pov(filename, scene=None, info_callback=None): ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z)) #################################################################################################### + def exportRainbows(rainbows): + for ob in rainbows: + povdataname = ob.data.name #enough? + angle = degrees(ob.data.spot_size/2.5) #radians in blender (2 + width = ob.data.spot_blend *10 + distance = ob.data.shadow_buffer_clip_start + #eps=0.0000001 + #angle = br/(cr+eps) * 10 #eps is small epsilon variable to avoid dividing by zero + #width = ob.dimensions[2] #now let's say width of rainbow is the actual proxy height + # formerly: + #cz-bz # let's say width of the rainbow is height of the cone (interfacing choice + + # v(A,B) rotates vector A about origin by vector B. + # and avoid a 0 length vector by adding 1 + + # file.write("#declare %s_Target= vrotate(<%.6g,%.6g,%.6g>,<%.4g,%.4g,%.4g>);\n" % \ + # (povdataname, -(ob.location.x+0.1), -(ob.location.y+0.1), -(ob.location.z+0.1), + # ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z)) + + direction = (ob.location.x,ob.location.y,ob.location.z) # not taking matrix into account + rmatrix = global_matrix * ob.matrix_world + + #ob.rotation_euler.to_matrix().to_4x4() * mathutils.Vector((0,0,1)) + # XXX Is result of the below offset by 90 degrees? + up =ob.matrix_world.to_3x3()[1].xyz #* global_matrix + + + # XXX TO CHANGE: + #formerly: + #tabWrite("#declare %s = rainbow {\n"%povdataname) + + # clumsy for now but remove the rainbow from instancing + # system because not an object. use lamps later instead of meshes + + #del data_ref[dataname] + tabWrite("rainbow {\n") + + tabWrite("angle %.4f\n"%angle) + tabWrite("width %.4f\n"%width) + tabWrite("distance %.4f\n"%distance) + tabWrite("arc_angle %.4f\n"%ob.pov.arc_angle) + tabWrite("falloff_angle %.4f\n"%ob.pov.falloff_angle) + tabWrite("direction <%.4f,%.4f,%.4f>\n"%rmatrix.translation[:]) + tabWrite("up <%.4f,%.4f,%.4f>\n"%(up[0],up[1],up[2])) + tabWrite("color_map {\n") + tabWrite("[0.000 color rgbt<1.0, 0.5, 1.0, 1.0>]\n") + tabWrite("[0.130 color rgbt<0.5, 0.5, 1.0, 0.9>]\n") + tabWrite("[0.298 color rgbt<0.2, 0.2, 1.0, 0.7>]\n") + tabWrite("[0.412 color rgbt<0.2, 1.0, 1.0, 0.4>]\n") + tabWrite("[0.526 color rgbt<0.2, 1.0, 0.2, 0.4>]\n") + tabWrite("[0.640 color rgbt<1.0, 1.0, 0.2, 0.4>]\n") + tabWrite("[0.754 color rgbt<1.0, 0.5, 0.2, 0.6>]\n") + tabWrite("[0.900 color rgbt<1.0, 0.2, 0.2, 0.7>]\n") + tabWrite("[1.000 color rgbt<1.0, 0.2, 0.2, 1.0>]\n") + tabWrite("}\n") + + + povMatName = "Default_texture" + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + #matrix = global_matrix * ob.matrix_world + #writeMatrix(matrix) + tabWrite("}\n") + #continue #Don't render proxy mesh, skip to next object + +################################XXX LOFT, ETC. + def exportCurves(scene, ob): + name_orig = "OB" + ob.name + dataname_orig = "DATA" + ob.data.name + + name = string_strip_hyphen(bpy.path.clean_name(name_orig)) + dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig)) + + global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X') + matrix=global_matrix*ob.matrix_world + bezier_sweep = False + if ob.pov.curveshape == 'sphere_sweep': + for spl in ob.data.splines: + if spl.type == "BEZIER": + bezier_sweep = True + if ob.pov.curveshape in {'loft','birail'}: + n=0 + for spline in ob.data.splines: + n+=1 + tabWrite('#declare %s%s=spline {\n'%(dataname,n)) + tabWrite('cubic_spline\n') + lp = len(spline.points) + delta = 1/(lp) + d=-delta + point = spline.points[lp-1] + x,y,z,w = point.co[:] + tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z)) + d+=delta + for point in spline.points: + x,y,z,w = point.co[:] + tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z)) + d+=delta + for i in range(2): + point = spline.points[i] + x,y,z,w = point.co[:] + tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z)) + d+=delta + tabWrite('}\n') + if ob.pov.curveshape in {'loft'}: + n = len(ob.data.splines) + tabWrite('#declare %s = array[%s]{\n'%(dataname,(n+3))) + tabWrite('spline{%s%s},\n'%(dataname,n)) + for i in range(n): + tabWrite('spline{%s%s},\n'%(dataname,(i+1))) + tabWrite('spline{%s1},\n'%(dataname)) + tabWrite('spline{%s2}\n'%(dataname)) + tabWrite('}\n') + # Use some of the Meshmaker.inc macro, here inlined + file.write('#macro CheckFileName(FileName)\n') + file.write(' #local Len=strlen(FileName);\n') + file.write(' #if(Len>0)\n') + file.write(' #if(file_exists(FileName))\n') + file.write(' #if(Len>=4)\n') + file.write(' #local Ext=strlwr(substr(FileName,Len-3,4))\n') + file.write(' #if (strcmp(Ext,".obj")=0 | strcmp(Ext,".pcm")=0 | strcmp(Ext,".arr")=0)\n') + file.write(' #local Return=99;\n') + file.write(' #else\n') + file.write(' #local Return=0;\n') + file.write(' #end\n') + file.write(' #else\n') + file.write(' #local Return=0;\n') + file.write(' #end\n') + file.write(' #else\n') + file.write(' #if(Len>=4)\n') + file.write(' #local Ext=strlwr(substr(FileName,Len-3,4))\n') + file.write(' #if (strcmp(Ext,".obj")=0 | strcmp(Ext,".pcm")=0 | strcmp(Ext,".arr")=0)\n') + file.write(' #if (strcmp(Ext,".obj")=0)\n') + file.write(' #local Return=2;\n') + file.write(' #end\n') + file.write(' #if (strcmp(Ext,".pcm")=0)\n') + file.write(' #local Return=3;\n') + file.write(' #end\n') + file.write(' #if (strcmp(Ext,".arr")=0)\n') + file.write(' #local Return=4;\n') + file.write(' #end\n') + file.write(' #else\n') + file.write(' #local Return=1;\n') + file.write(' #end\n') + file.write(' #else\n') + file.write(' #local Return=1;\n') + file.write(' #end\n') + file.write(' #end\n') + file.write(' #else\n') + file.write(' #local Return=1;\n') + file.write(' #end\n') + file.write(' (Return)\n') + file.write('#end\n') + + file.write('#macro BuildSpline(Arr, SplType)\n') + file.write(' #local Ds=dimension_size(Arr,1);\n') + file.write(' #local Asc=asc(strupr(SplType));\n') + file.write(' #if(Asc!=67 & Asc!=76 & Asc!=81) \n') + file.write(' #local Asc=76;\n') + file.write(' #debug "\nWrong spline type defined (C/c/L/l/N/n/Q/q), using default linear_spline\\n"\n') + file.write(' #end\n') + file.write(' spline {\n') + file.write(' #switch (Asc)\n') + file.write(' #case (67) //C cubic_spline\n') + file.write(' cubic_spline\n') + file.write(' #break\n') + file.write(' #case (76) //L linear_spline\n') + file.write(' linear_spline\n') + file.write(' #break\n') + file.write(' #case (78) //N linear_spline\n') + file.write(' natural_spline\n') + file.write(' #break\n') + file.write(' #case (81) //Q Quadratic_spline\n') + file.write(' quadratic_spline\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' #local Add=1/((Ds-2)-1);\n') + file.write(' #local J=0-Add;\n') + file.write(' #local I=0;\n') + file.write(' #while (I<Ds)\n') + file.write(' J\n') + file.write(' Arr[I]\n') + file.write(' #local I=I+1;\n') + file.write(' #local J=J+Add;\n') + file.write(' #end\n') + file.write(' }\n') + file.write('#end\n') + + + file.write('#macro BuildWriteMesh2(VecArr, NormArr, UVArr, U, V, FileName)\n') + #suppressed some file checking from original macro because no more separate files + file.write(' #local Write=0;\n') + file.write(' #debug concat("\\n\\n Building mesh2: \\n - vertex_vectors\\n")\n') + file.write(' #local NumVertices=dimension_size(VecArr,1);\n') + file.write(' #switch (Write)\n') + file.write(' #case(1)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' " vertex_vectors {\\n",\n') + file.write(' " ", str(NumVertices,0,0),"\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "# Vertices: ",str(NumVertices,0,0),"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' str(2*NumVertices,0,0),",\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "#declare VertexVectors= array[",str(NumVertices,0,0),"] {\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' mesh2 {\n') + file.write(' vertex_vectors {\n') + file.write(' NumVertices\n') + file.write(' #local I=0;\n') + file.write(' #while (I<NumVertices)\n') + file.write(' VecArr[I]\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile, VecArr[I])\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "v ", VecArr[I].x," ", VecArr[I].y," ", VecArr[I].z,"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' VecArr[I].x,",", VecArr[I].y,",", VecArr[I].z,",\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile, VecArr[I])\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' #local I=I+1;\n') + file.write(' #if(Write=1 | Write=4)\n') + file.write(' #if(mod(I,3)=0)\n') + file.write(' #write(MeshFile,"\\n ")\n') + file.write(' #end\n') + file.write(' #end \n') + file.write(' #end\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile,"\\n }\\n")\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(MeshFile,"\\n")\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' // do nothing\n') + file.write(' #break\n') + file.write(' #case(4) \n') + file.write(' #write(MeshFile,"\\n}\\n")\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' }\n') + + file.write(' #debug concat(" - normal_vectors\\n") \n') + file.write(' #local NumVertices=dimension_size(NormArr,1);\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' " normal_vectors {\\n",\n') + file.write(' " ", str(NumVertices,0,0),"\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "# Normals: ",str(NumVertices,0,0),"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' // do nothing\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "#declare NormalVectors= array[",str(NumVertices,0,0),"] {\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' normal_vectors {\n') + file.write(' NumVertices\n') + file.write(' #local I=0;\n') + file.write(' #while (I<NumVertices)\n') + file.write(' NormArr[I]\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile NormArr[I])\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "vn ", NormArr[I].x," ", NormArr[I].y," ", NormArr[I].z,"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' NormArr[I].x,",", NormArr[I].y,",", NormArr[I].z,",\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile NormArr[I])\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' #local I=I+1;\n') + file.write(' #if(Write=1 | Write=4) \n') + file.write(' #if(mod(I,3)=0)\n') + file.write(' #write(MeshFile,"\\n ")\n') + file.write(' #end\n') + file.write(' #end\n') + file.write(' #end\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile,"\\n }\\n")\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(MeshFile,"\\n")\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' //do nothing\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile,"\\n}\\n")\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' }\n') + + file.write(' #debug concat(" - uv_vectors\\n") \n') + file.write(' #local NumVertices=dimension_size(UVArr,1);\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(\n') + file.write(' MeshFile, \n') + file.write(' " uv_vectors {\\n",\n') + file.write(' " ", str(NumVertices,0,0),"\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "# UV-vectors: ",str(NumVertices,0,0),"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' // do nothing, *.pcm does not support uv-vectors\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "#declare UVVectors= array[",str(NumVertices,0,0),"] {\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' uv_vectors {\n') + file.write(' NumVertices\n') + file.write(' #local I=0;\n') + file.write(' #while (I<NumVertices)\n') + file.write(' UVArr[I]\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile UVArr[I])\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "vt ", UVArr[I].u," ", UVArr[I].v,"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' //do nothing\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile UVArr[I])\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' #local I=I+1; \n') + file.write(' #if(Write=1 | Write=4)\n') + file.write(' #if(mod(I,3)=0)\n') + file.write(' #write(MeshFile,"\\n ")\n') + file.write(' #end \n') + file.write(' #end\n') + file.write(' #end \n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile,"\\n }\\n")\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(MeshFile,"\\n")\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' //do nothing\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile,"\\n}\\n")\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' }\n') + file.write('\n') + file.write(' #debug concat(" - face_indices\\n") \n') + file.write(' #declare NumFaces=U*V*2;\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' " face_indices {\\n"\n') + file.write(' " ", str(NumFaces,0,0),"\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write (\n') + file.write(' MeshFile,\n') + file.write(' "# faces: ",str(NumFaces,0,0),"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #write (\n') + file.write(' MeshFile,\n') + file.write(' "0,",str(NumFaces,0,0),",\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "#declare FaceIndices= array[",str(NumFaces,0,0),"] {\\n "\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' face_indices {\n') + file.write(' NumFaces\n') + file.write(' #local I=0;\n') + file.write(' #local H=0;\n') + file.write(' #local NumVertices=dimension_size(VecArr,1);\n') + file.write(' #while (I<V)\n') + file.write(' #local J=0;\n') + file.write(' #while (J<U)\n') + file.write(' #local Ind=(I*U)+I+J;\n') + file.write(' <Ind, Ind+1, Ind+U+2>, <Ind, Ind+U+1, Ind+U+2>\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' <Ind, Ind+1, Ind+U+2>, <Ind, Ind+U+1, Ind+U+2>\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' "f ",Ind+1,"/",Ind+1,"/",Ind+1," ",Ind+1+1,"/",Ind+1+1,"/",Ind+1+1," ",Ind+U+2+1,"/",Ind+U+2+1,"/",Ind+U+2+1,"\\n",\n') + file.write(' "f ",Ind+U+1+1,"/",Ind+U+1+1,"/",Ind+U+1+1," ",Ind+1,"/",Ind+1,"/",Ind+1," ",Ind+U+2+1,"/",Ind+U+2+1,"/",Ind+U+2+1,"\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' Ind,",",Ind+NumVertices,",",Ind+1,",",Ind+1+NumVertices,",",Ind+U+2,",",Ind+U+2+NumVertices,",\\n"\n') + file.write(' Ind+U+1,",",Ind+U+1+NumVertices,",",Ind,",",Ind+NumVertices,",",Ind+U+2,",",Ind+U+2+NumVertices,",\\n"\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(\n') + file.write(' MeshFile,\n') + file.write(' <Ind, Ind+1, Ind+U+2>, <Ind, Ind+U+1, Ind+U+2>\n') + file.write(' )\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' #local J=J+1;\n') + file.write(' #local H=H+1;\n') + file.write(' #if(Write=1 | Write=4)\n') + file.write(' #if(mod(H,3)=0)\n') + file.write(' #write(MeshFile,"\\n ")\n') + file.write(' #end \n') + file.write(' #end\n') + file.write(' #end\n') + file.write(' #local I=I+1;\n') + file.write(' #end\n') + file.write(' }\n') + file.write(' #switch(Write)\n') + file.write(' #case(1)\n') + file.write(' #write(MeshFile, "\\n }\\n}")\n') + file.write(' #fclose MeshFile\n') + file.write(' #debug concat(" Done writing\\n")\n') + file.write(' #break\n') + file.write(' #case(2)\n') + file.write(' #fclose MeshFile\n') + file.write(' #debug concat(" Done writing\\n")\n') + file.write(' #break\n') + file.write(' #case(3)\n') + file.write(' #fclose MeshFile\n') + file.write(' #debug concat(" Done writing\\n")\n') + file.write(' #break\n') + file.write(' #case(4)\n') + file.write(' #write(MeshFile, "\\n}\\n}")\n') + file.write(' #fclose MeshFile\n') + file.write(' #debug concat(" Done writing\\n")\n') + file.write(' #break\n') + file.write(' #end\n') + file.write(' }\n') + file.write('#end\n') + + file.write('#macro MSM(SplineArray, SplRes, Interp_type, InterpRes, FileName)\n') + file.write(' #declare Build=CheckFileName(FileName);\n') + file.write(' #if(Build=0)\n') + file.write(' #debug concat("\\n Parsing mesh2 from file: ", FileName, "\\n")\n') + file.write(' #include FileName\n') + file.write(' object{Surface}\n') + file.write(' #else\n') + file.write(' #local NumVertices=(SplRes+1)*(InterpRes+1);\n') + file.write(' #local NumFaces=SplRes*InterpRes*2;\n') + file.write(' #debug concat("\\n Calculating ",str(NumVertices,0,0)," vertices for ", str(NumFaces,0,0)," triangles\\n\\n")\n') + file.write(' #local VecArr=array[NumVertices]\n') + file.write(' #local NormArr=array[NumVertices]\n') + file.write(' #local UVArr=array[NumVertices]\n') + file.write(' #local N=dimension_size(SplineArray,1);\n') + file.write(' #local TempSplArr0=array[N];\n') + file.write(' #local TempSplArr1=array[N];\n') + file.write(' #local TempSplArr2=array[N];\n') + file.write(' #local PosStep=1/SplRes;\n') + file.write(' #local InterpStep=1/InterpRes;\n') + file.write(' #local Count=0;\n') + file.write(' #local Pos=0;\n') + file.write(' #while(Pos<=1)\n') + file.write(' #local I=0;\n') + file.write(' #if (Pos=0)\n') + file.write(' #while (I<N)\n') + file.write(' #local Spl=spline{SplineArray[I]}\n') + file.write(' #local TempSplArr0[I]=<0,0,0>+Spl(Pos);\n') + file.write(' #local TempSplArr1[I]=<0,0,0>+Spl(Pos+PosStep);\n') + file.write(' #local TempSplArr2[I]=<0,0,0>+Spl(Pos-PosStep);\n') + file.write(' #local I=I+1;\n') + file.write(' #end\n') + file.write(' #local S0=BuildSpline(TempSplArr0, Interp_type)\n') + file.write(' #local S1=BuildSpline(TempSplArr1, Interp_type)\n') + file.write(' #local S2=BuildSpline(TempSplArr2, Interp_type)\n') + file.write(' #else\n') + file.write(' #while (I<N)\n') + file.write(' #local Spl=spline{SplineArray[I]}\n') + file.write(' #local TempSplArr1[I]=<0,0,0>+Spl(Pos+PosStep);\n') + file.write(' #local I=I+1;\n') + file.write(' #end\n') + file.write(' #local S1=BuildSpline(TempSplArr1, Interp_type)\n') + file.write(' #end\n') + file.write(' #local J=0;\n') + file.write(' #while (J<=1)\n') + file.write(' #local P0=<0,0,0>+S0(J);\n') + file.write(' #local P1=<0,0,0>+S1(J);\n') + file.write(' #local P2=<0,0,0>+S2(J);\n') + file.write(' #local P3=<0,0,0>+S0(J+InterpStep);\n') + file.write(' #local P4=<0,0,0>+S0(J-InterpStep);\n') + file.write(' #local B1=P4-P0;\n') + file.write(' #local B2=P2-P0;\n') + file.write(' #local B3=P3-P0;\n') + file.write(' #local B4=P1-P0;\n') + file.write(' #local N1=vcross(B1,B2);\n') + file.write(' #local N2=vcross(B2,B3);\n') + file.write(' #local N3=vcross(B3,B4);\n') + file.write(' #local N4=vcross(B4,B1);\n') + file.write(' #local Norm=vnormalize((N1+N2+N3+N4));\n') + file.write(' #local VecArr[Count]=P0;\n') + file.write(' #local NormArr[Count]=Norm;\n') + file.write(' #local UVArr[Count]=<J,Pos>;\n') + file.write(' #local J=J+InterpStep;\n') + file.write(' #local Count=Count+1;\n') + file.write(' #end\n') + file.write(' #local S2=spline{S0}\n') + file.write(' #local S0=spline{S1}\n') + file.write(' #debug concat("\\r Done ", str(Count,0,0)," vertices : ", str(100*Count/NumVertices,0,2)," %")\n') + file.write(' #local Pos=Pos+PosStep;\n') + file.write(' #end\n') + file.write(' BuildWriteMesh2(VecArr, NormArr, UVArr, InterpRes, SplRes, "")\n') + file.write(' #end\n') + file.write('#end\n\n') + + file.write('#macro Coons(Spl1, Spl2, Spl3, Spl4, Iter_U, Iter_V, FileName)\n') + file.write(' #declare Build=CheckFileName(FileName);\n') + file.write(' #if(Build=0)\n') + file.write(' #debug concat("\\n Parsing mesh2 from file: ", FileName, "\\n")\n') + file.write(' #include FileName\n') + file.write(' object{Surface}\n') + file.write(' #else\n') + file.write(' #local NumVertices=(Iter_U+1)*(Iter_V+1);\n') + file.write(' #local NumFaces=Iter_U*Iter_V*2;\n') + file.write(' #debug concat("\\n Calculating ", str(NumVertices,0,0), " vertices for ",str(NumFaces,0,0), " triangles\\n\\n")\n') + file.write(' #declare VecArr=array[NumVertices] \n') + file.write(' #declare NormArr=array[NumVertices] \n') + file.write(' #local UVArr=array[NumVertices] \n') + file.write(' #local Spl1_0=Spl1(0);\n') + file.write(' #local Spl2_0=Spl2(0);\n') + file.write(' #local Spl3_0=Spl3(0);\n') + file.write(' #local Spl4_0=Spl4(0);\n') + file.write(' #local UStep=1/Iter_U;\n') + file.write(' #local VStep=1/Iter_V;\n') + file.write(' #local Count=0;\n') + file.write(' #local I=0;\n') + file.write(' #while (I<=1)\n') + file.write(' #local Im=1-I;\n') + file.write(' #local J=0;\n') + file.write(' #while (J<=1)\n') + file.write(' #local Jm=1-J;\n') + file.write(' #local C0=Im*Jm*(Spl1_0)+Im*J*(Spl2_0)+I*J*(Spl3_0)+I*Jm*(Spl4_0);\n') + file.write(' #local P0=LInterpolate(I, Spl1(J), Spl3(Jm)) + \n') + file.write(' LInterpolate(Jm, Spl2(I), Spl4(Im))-C0;\n') + file.write(' #declare VecArr[Count]=P0;\n') + file.write(' #local UVArr[Count]=<J,I>;\n') + file.write(' #local J=J+UStep;\n') + file.write(' #local Count=Count+1;\n') + file.write(' #end\n') + file.write(' #debug concat(\n') + file.write(' "\r Done ", str(Count,0,0)," vertices : ",\n') + file.write(' str(100*Count/NumVertices,0,2)," %"\n') + file.write(' )\n') + file.write(' #local I=I+VStep;\n') + file.write(' #end\n') + file.write(' #debug "\r Normals "\n') + file.write(' #local Count=0;\n') + file.write(' #local I=0;\n') + file.write(' #while (I<=Iter_V)\n') + file.write(' #local J=0;\n') + file.write(' #while (J<=Iter_U)\n') + file.write(' #local Ind=(I*Iter_U)+I+J;\n') + file.write(' #local P0=VecArr[Ind];\n') + file.write(' #if(J=0)\n') + file.write(' #local P1=P0+(P0-VecArr[Ind+1]);\n') + file.write(' #else\n') + file.write(' #local P1=VecArr[Ind-1];\n') + file.write(' #end\n') + file.write(' #if (J=Iter_U)\n') + file.write(' #local P2=P0+(P0-VecArr[Ind-1]);\n') + file.write(' #else\n') + file.write(' #local P2=VecArr[Ind+1];\n') + file.write(' #end\n') + file.write(' #if (I=0)\n') + file.write(' #local P3=P0+(P0-VecArr[Ind+Iter_U+1]);\n') + file.write(' #else\n') + file.write(' #local P3=VecArr[Ind-Iter_U-1];\n') + file.write(' #end\n') + file.write(' #if (I=Iter_V)\n') + file.write(' #local P4=P0+(P0-VecArr[Ind-Iter_U-1]);\n') + file.write(' #else\n') + file.write(' #local P4=VecArr[Ind+Iter_U+1];\n') + file.write(' #end\n') + file.write(' #local B1=P4-P0;\n') + file.write(' #local B2=P2-P0;\n') + file.write(' #local B3=P3-P0;\n') + file.write(' #local B4=P1-P0;\n') + file.write(' #local N1=vcross(B1,B2);\n') + file.write(' #local N2=vcross(B2,B3);\n') + file.write(' #local N3=vcross(B3,B4);\n') + file.write(' #local N4=vcross(B4,B1);\n') + file.write(' #local Norm=vnormalize((N1+N2+N3+N4));\n') + file.write(' #declare NormArr[Count]=Norm;\n') + file.write(' #local J=J+1;\n') + file.write(' #local Count=Count+1;\n') + file.write(' #end\n') + file.write(' #debug concat("\r Done ", str(Count,0,0)," normals : ",str(100*Count/NumVertices,0,2), " %")\n') + file.write(' #local I=I+1;\n') + file.write(' #end\n') + file.write(' BuildWriteMesh2(VecArr, NormArr, UVArr, Iter_U, Iter_V, FileName)\n') + file.write(' #end\n') + file.write('#end\n\n') + + if bezier_sweep == False: + tabWrite("#declare %s =\n"%dataname) + if ob.pov.curveshape == 'sphere_sweep' and bezier_sweep == False: + tabWrite("union {\n") + for spl in ob.data.splines: + if spl.type != "BEZIER": + spl_type = "linear" + if spl.type == "NURBS": + spl_type = "cubic" + points=spl.points + numPoints=len(points) + if spl.use_cyclic_u: + numPoints+=3 + + tabWrite("sphere_sweep { %s_spline %s,\n"%(spl_type,numPoints)) + if spl.use_cyclic_u: + pt1 = points[len(points)-1] + wpt1 = pt1.co + tabWrite("<%.4g,%.4g,%.4g>,%.4g\n" %(wpt1[0], wpt1[1], wpt1[2], pt1.radius*ob.data.bevel_depth)) + for pt in points: + wpt = pt.co + tabWrite("<%.4g,%.4g,%.4g>,%.4g\n" %(wpt[0], wpt[1], wpt[2], pt.radius*ob.data.bevel_depth)) + if spl.use_cyclic_u: + for i in range (0,2): + endPt=points[i] + wpt = endPt.co + tabWrite("<%.4g,%.4g,%.4g>,%.4g\n" %(wpt[0], wpt[1], wpt[2], endPt.radius*ob.data.bevel_depth)) + + + tabWrite("}\n") + if ob.pov.curveshape == 'sor': + for spl in ob.data.splines: + if spl.type in {'POLY','NURBS'}: + points=spl.points + numPoints=len(points) + tabWrite("sor { %s,\n"%numPoints) + for pt in points: + wpt = pt.co + tabWrite("<%.4g,%.4g>\n" %(wpt[0], wpt[1])) + else: + tabWrite("box { 0,0\n") + if ob.pov.curveshape in {'lathe','prism'}: + spl = ob.data.splines[0] + if spl.type == "BEZIER": + points=spl.bezier_points + lenCur=len(points)-1 + lenPts=lenCur*4 + ifprism = '' + if ob.pov.curveshape in {'prism'}: + height = ob.data.extrude + ifprism = '-%s, %s,'%(height, height) + lenCur+=1 + lenPts+=4 + tabWrite("%s { bezier_spline %s %s,\n"%(ob.pov.curveshape,ifprism,lenPts)) + for i in range(0,lenCur): + p1=points[i].co + pR=points[i].handle_right + end = i+1 + if i == lenCur-1 and ob.pov.curveshape in {'prism'}: + end = 0 + pL=points[end].handle_left + p2=points[end].co + line="<%.4g,%.4g>"%(p1[0],p1[1]) + line+="<%.4g,%.4g>"%(pR[0],pR[1]) + line+="<%.4g,%.4g>"%(pL[0],pL[1]) + line+="<%.4g,%.4g>"%(p2[0],p2[1]) + tabWrite("%s\n" %line) + else: + points=spl.points + lenCur=len(points) + lenPts=lenCur + ifprism = '' + if ob.pov.curveshape in {'prism'}: + height = ob.data.extrude + ifprism = '-%s, %s,'%(height, height) + lenPts+=3 + spl_type = 'quadratic' + if spl.type == 'POLY': + spl_type = 'linear' + tabWrite("%s { %s_spline %s %s,\n"%(ob.pov.curveshape,spl_type,ifprism,lenPts)) + if ob.pov.curveshape in {'prism'}: + pt = points[len(points)-1] + wpt = pt.co + tabWrite("<%.4g,%.4g>\n" %(wpt[0], wpt[1])) + for pt in points: + wpt = pt.co + tabWrite("<%.4g,%.4g>\n" %(wpt[0], wpt[1])) + if ob.pov.curveshape in {'prism'}: + for i in range(2): + pt = points[i] + wpt = pt.co + tabWrite("<%.4g,%.4g>\n" %(wpt[0], wpt[1])) + if bezier_sweep: + spl = ob.data.splines[0] + points=spl.bezier_points + lenCur = len(points)-1 + numPoints = lenCur*4 + if spl.use_cyclic_u: + lenCur += 1 + numPoints += 4 + tabWrite("#declare %s_bezier_points = array[%s]{\n"%(dataname,numPoints)) + for i in range(lenCur): + p1=points[i].co + pR=points[i].handle_right + end = i+1 + if spl.use_cyclic_u and i == (lenCur - 1): + end = 0 + pL=points[end].handle_left + p2=points[end].co + line="<%.4g,%.4g,%.4f>"%(p1[0],p1[1],p1[2]) + line+="<%.4g,%.4g,%.4f>"%(pR[0],pR[1],pR[2]) + line+="<%.4g,%.4g,%.4f>"%(pL[0],pL[1],pL[2]) + line+="<%.4g,%.4g,%.4f>"%(p2[0],p2[1],p2[2]) + tabWrite("%s\n" %line) + tabWrite("}\n") + #tabWrite('#include "bezier_spheresweep.inc"\n') #now inlined + tabWrite('#declare %s = object{Shape_Bezierpoints_Sphere_Sweep(%s, %s_bezier_points, %.4f) \n'%(dataname,ob.data.resolution_u,dataname,ob.data.bevel_depth)) + if ob.pov.curveshape in {'loft'}: + tabWrite('object {MSM(%s,%s,"c",%s,"")\n'%(dataname,ob.pov.res_u,ob.pov.res_v)) + if ob.pov.curveshape in {'birail'}: + splines = '%s1,%s2,%s3,%s4'%(dataname,dataname,dataname,dataname) + tabWrite('object {Coons(%s, %s, %s, "")\n'%(splines,ob.pov.res_u,ob.pov.res_v)) + 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) + if ob.pov.curveshape in {'prism'}: + tabWrite("rotate <90,0,0>\n") + tabWrite("scale y*-1\n" ) + tabWrite("}\n") + +################################################################# + + def exportMeta(metas): # TODO - blenders 'motherball' naming is not supported. @@ -1452,24 +2392,24 @@ def write_pov(filename, scene=None, info_callback=None): # channeldata = fire # sc_fr = '%s/%s/%s/%05d' % (efutil.export_path, efutil.scene_filename(), bpy.context.scene.name, bpy.context.scene.frame_current) - # if not os.path.exists( sc_fr ): - # os.makedirs(sc_fr) + # if not os.path.exists( sc_fr ): + # os.makedirs(sc_fr) # - # smoke_filename = '%s.smoke' % bpy.path.clean_name(domain.name) - # smoke_path = '/'.join([sc_fr, smoke_filename]) + # smoke_filename = '%s.smoke' % bpy.path.clean_name(domain.name) + # smoke_path = '/'.join([sc_fr, smoke_filename]) # - # with open(smoke_path, 'wb') as smoke_file: - # # Binary densitygrid file format - # # - # # File header - # smoke_file.write(b'SMOKE') #magic number - # smoke_file.write(struct.pack('<I', big_res[0])) - # smoke_file.write(struct.pack('<I', big_res[1])) - # smoke_file.write(struct.pack('<I', big_res[2])) + # with open(smoke_path, 'wb') as smoke_file: + # # Binary densitygrid file format + # # + # # File header + # smoke_file.write(b'SMOKE') #magic number + # smoke_file.write(struct.pack('<I', big_res[0])) + # smoke_file.write(struct.pack('<I', big_res[1])) + # smoke_file.write(struct.pack('<I', big_res[2])) # Density data - # smoke_file.write(struct.pack('<%df'%len(channeldata), *channeldata)) + # smoke_file.write(struct.pack('<%df'%len(channeldata), *channeldata)) # - # LuxLog('Binary SMOKE file written: %s' % (smoke_path)) + # LuxLog('Binary SMOKE file written: %s' % (smoke_path)) #return big_res[0], big_res[1], big_res[2], channeldata @@ -1533,9 +2473,9 @@ def write_pov(filename, scene=None, info_callback=None): file.write("}\n") - #file.write(" interpolate 1\n") - #file.write(" frequency 0\n") - #file.write(" }\n") + #file.write(" interpolate 1\n") + #file.write(" frequency 0\n") + #file.write(" }\n") #file.write("}\n") ob_num = 0 @@ -1544,7 +2484,8 @@ def write_pov(filename, scene=None, info_callback=None): # 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 {'LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'}: + if (ob.type in {'LAMP', 'CAMERA', 'EMPTY', + 'META', 'ARMATURE', 'LATTICE'}): continue smokeFlag=False for mod in ob.modifiers: @@ -1734,18 +2675,6 @@ def write_pov(filename, scene=None, info_callback=None): if renderEmitter == False: continue #don't render mesh, skip to next object. - try: - me = ob.to_mesh(scene, True, 'RENDER') - except: - # happens when curves cant be made into meshes because of no-data - continue - - 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 @@ -1780,265 +2709,596 @@ def write_pov(filename, scene=None, info_callback=None): continue print("Writing Down First Occurence") + +############################################Povray Primitives + # special exportCurves() function takes care of writing + # lathe, sphere_sweep, birail, and loft + 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 - 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: - uv_layer = None + 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: + 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 - try: - #vcol_layer = me.vertex_colors.active.data - vcol_layer = me.tessface_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] + 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': + tabWrite("#declare %s = cylinder { <0,0,1>,<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 == '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 - # quads incur an extra face - 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") - 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 + 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") else: - file.write(", ") - file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count - #tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count - file.write("\n") - tabWrite("}\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 + + 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 - # 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 + +############################################else try to export mesh + else: + try: + me = ob.to_mesh(scene, True, 'RENDER') + except: + # happens when curves cant be made into meshes because of no-data + continue + + importance = ob.pov.importance_value + me_materials = me.materials + me_faces = me.tessfaces[:] + + if not me or not me_faces: + continue + + 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: - file.write(", ") - file.write("<%.6f, %.6f, %.6f>" % no) # vert count - index[0] = idx - idx += 1 - file.write("\n") - tabWrite("}\n") + uv_layer = None + + try: + #vcol_layer = me.vertex_colors.active.data + vcol_layer = me.tessface_vertex_colors.active.data + except AttributeError: + vcol_layer = None - # Vertex colors - vertCols = {} # Use for material colors also. + 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] - if uv_layer: - # Generate unique UV's - uniqueUVs = {} - #n = 0 - for fi, uv in enumerate(uv_layer): + # quads incur an extra face + 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") + tabWrite("#declare %s =\n" % povdataname) + tabWrite("mesh2 {\n") + tabWrite("vertex_vectors {\n") + tabWrite("%d" % len(me.vertices)) # vert count - 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] + tabStr = tab * tabLevel + for v in me.vertices: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count else: - uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2] + file.write(", ") + file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count + #tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count + file.write("\n") + tabWrite("}\n") - for uv in uvs: - uniqueUVs[uv[:]] = [-1] + # 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("uv_vectors {\n") - #print unique_uvs - tabWrite("%d" % len(uniqueUVs)) # vert count + tabWrite("normal_vectors {\n") + tabWrite("%d" % len(uniqueNormals)) # vert count idx = 0 tabStr = tab * tabLevel - for uv, index in uniqueUVs.items(): + for no, index in uniqueNormals.items(): if linebreaksinlists: file.write(",\n") - file.write(tabStr + "<%.6f, %.6f>" % uv) + file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count else: file.write(", ") - file.write("<%.6f, %.6f>" % uv) + file.write("<%.6f, %.6f, %.6f>" % no) # vert count index[0] = idx idx += 1 - ''' - else: - # 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)-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 - 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 - - col = vcol_layer[fi] + # 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: - cols = col.color1, col.color2, col.color3, col.color4 + uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2], uv_layer[fi].uv[3] 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 - else: - if material: - # 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[:])] - 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) + 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),) + uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2] - if vcol_layer: - col = vcol_layer[fi] + for uv in uvs: + uniqueUVs[uv[:]] = [-1] - if len(fv) == 4: - cols = col.color1, col.color2, col.color3, col.color4 + 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) 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: - if linebreaksinlists: - 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 + file.write(", ") + file.write("<%.6f, %.6f>" % uv) + index[0] = idx + idx += 1 + ''' 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] + # 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") - 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] + if me.vertex_colors: + #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 + 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 + + col = vcol_layer[fi] + + if len(faces_verts[fi]) == 4: + cols = col.color1, col.color2, col.color3, col.color4 else: - # Color per material - flat material color + 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 + else: + if material: + # 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[:])] + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ + material_index + vertCols[key] = [-1] 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[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 + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ + material_index + vertCols[key] = [-1] - file.write("\n") - tabWrite("}\n") + tabWrite("\n}\n") + # Face indices + tabWrite("\nface_indices {\n") + tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabStr = tab * tabLevel - # 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): + 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 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: - if linebreaksinlists: - 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 + if vcol_layer: + col = vcol_layer[fi] + + if len(fv) == 4: + cols = col.color1, col.color2, col.color3, col.color4 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 + 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: + if linebreaksinlists: + 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: - 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 + 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 + if linebreaksinlists: + 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") + file.write("\n") + tabWrite("}\n") - if uv_layer: - tabWrite("uv_indices {\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): @@ -2048,256 +3308,418 @@ def write_pov(filename, scene=None, info_callback=None): 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: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + if me_faces[fi].use_smooth: + if linebreaksinlists: + 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: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + 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 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") + 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): - tabWrite("}\n") # End of mesh block - else: - # No vertex colors, so write material colors as vertex colors - for i, material in enumerate(me_materials): - - if material: - # 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[:])] - 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] - - idx = 0 - LocalMaterialNames = [] - for col, index in vertCols.items(): - #if me_materials: - mater = me_materials[col[3]] - if me_materials is None: #XXX working? - material_finish = DEF_MAT_NAME # not working properly, - trans = 0.0 + 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: - material_finish = materialNames[mater.name] - if mater.use_transparency: - trans = 1.0 - mater.alpha + uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:] + + for i1, i2, i3 in indices: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % ( + uniqueUVs[uvs[i1]][0],\ + uniqueUVs[uvs[i2]][0],\ + uniqueUVs[uvs[i3]][0])) else: - trans = 0.0 - if (mater.specular_color.s == 0.0): - colored_specular_found = False - else: - colored_specular_found = True + 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 + else: + # No vertex colors, so write material colors as vertex colors + for i, material in enumerate(me_materials): + + if material: + # 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[:])] + 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] + + idx = 0 + LocalMaterialNames = [] + for col, index in vertCols.items(): + #if me_materials: + mater = me_materials[col[3]] + if me_materials is None: #XXX working? + material_finish = DEF_MAT_NAME # not working properly, + trans = 0.0 - if mater.use_transparency and mater.transparency_method == 'RAYTRACE': - povFilter = mater.raytrace_transparency.filter * (1.0 - mater.alpha) - trans = (1.0 - mater.alpha) - povFilter else: - povFilter = 0.0 + material_finish = materialNames[mater.name] + if mater.use_transparency: + trans = 1.0 - mater.alpha + else: + trans = 0.0 + if (mater.specular_color.s == 0.0): + 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 + else: + povFilter = 0.0 + + ##############SF + texturesDif = "" + texturesSpec = "" + texturesNorm = "" + texturesAlpha = "" + #proceduralFlag=False + for t in mater.texture_slots: + 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 = bpy.utils.resource_path('USER') + 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) + # 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 + 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]) + LocalMaterialNames.append(currentMatName) + file.write("\n #declare MAT_%s = \ntexture{\n" % currentMatName) + + ################################################################################ - ##############SF - texturesDif = "" - texturesSpec = "" - texturesNorm = "" - texturesAlpha = "" - #proceduralFlag=False - for t in mater.texture_slots: - 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 = bpy.utils.resource_path('USER') - 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) - # 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 - 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]) - 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': - 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))) - - if mater.diffuse_shader == 'FRESNEL': - # 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)) + if mater.pov.replacement_text != "": + file.write("%s\n" % mater.pov.replacement_text) + ################################################################################# + if mater.diffuse_shader == 'MINNAERT': + tabWrite("\n") + tabWrite("aoi\n") 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))) - 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) + (mater.darkness / 2.0, 2.0 - mater.darkness)) + tabWrite("[%.3g\n" % (1.0 - (mater.darkness / 2.0))) + + if mater.diffuse_shader == 'FRESNEL': + # 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))) + 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 =imgMapTransforms(t_spec) + # 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) + 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 = imgMapTransforms(t_alpha) + # 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)) + 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") + + else: + + tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \ + (col[0], col[1], col[2], povFilter, trans)) + + if texturesSpec != "": + # Level 1 is no specular + tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) + + else: + # Level 2 is translated spec + tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) + else: + mappingDif = imgMapTransforms(t_dif) + + if texturesAlpha != "": + mappingAlpha = imgMapTransforms(t_alpha) + # 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)) + 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) + tabWrite("}\n") + tabWrite("}\n") + if texturesAlpha and texturesAlpha.startswith("PAT_"): + tabWrite("}\n") + + 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)) + + if texturesSpec != "": + # Level 1 is no specular + tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) + + 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 - mappingSpec =imgMapTransforms(t_spec) - # 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) - tabWrite("}\n") - tabWrite("texture_map {\n") - tabWrite("[0 \n") + mappingNor =imgMapTransforms(t_nor) + # 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)) + if texturesSpec != "": + tabWrite("]\n") + ##################Second index for mapping specular max value############### + tabWrite("[1 \n") - if texturesDif == "": + if texturesDif == "" and mater.pov.replacement_text == "": if texturesAlpha != "": - tabWrite("\n") + # 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 = imgMapTransforms(t_alpha) + # 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: - # 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 = imgMapTransforms(t_alpha) - # 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)) - tabWrite("}\n") + "{%s \"%s\" %s}%s}\n" % \ + (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), + mappingAlpha)) tabWrite("pigment_map {\n") tabWrite("[0 color rgbft<0,0,0,1,1>]\n") tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \ @@ -2306,441 +3728,294 @@ def write_pov(filename, scene=None, info_callback=None): tabWrite("}\n") 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))) + + elif colored_specular_found: # Level 1 is no specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) else: - # Level 2 is translated spec + # Level 2 is translated specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) - else: + elif mater.pov.replacement_text == "": mappingDif = imgMapTransforms(t_dif) - + # mappingDif = ("scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>" % \ + # ( 1.0 / t_dif.scale.x, + # 1.0 / t_dif.scale.y, + # 1.0 / t_dif.scale.z, + # 0.5-(0.5/t_dif.scale.x) + t_dif.offset.x, + # 0.5-(0.5/t_dif.scale.y) + t_dif.offset.y, + # 0.5-(0.5/t_dif.scale.z) + t_dif.offset.z)) if texturesAlpha != "": + # Strange that the translation factor for scale is not the same as for + # translate. + # TODO: verify both matches with blender internal. mappingAlpha = imgMapTransforms(t_alpha) - # 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") + # 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) if texturesAlpha and texturesAlpha.startswith("PAT_"): - tabWrite("function{f%s(x,y,z).transmit}\n" %texturesAlpha) + tabWrite("pigment{pigment_pattern {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)) + tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ + "{%s \"%s\" %s}%s}\n" % \ + (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), + mappingAlpha)) 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_"): + if texturesAlpha and texturesAlpha.startswith("PAT_"): + tabWrite("[1 function{f%s(x,y,z).transmit}]\n" %texturesAlpha) + elif 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)) + (imgMap(t_dif) + imgGamma), mappingDif)) elif texturesDif and texturesDif.startswith("PAT_"): - tabWrite("[1 %s]\n" %texturesDif) + tabWrite("[1 %s]\n" %texturesDif) tabWrite("}\n") tabWrite("}\n") - if texturesAlpha and texturesAlpha.startswith("PAT_"): - tabWrite("}\n") 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)) - + else: + tabWrite("pigment {\n") + tabWrite("uv_mapping image_map {\n") + #tabWrite("%s \"%s\" %s}%s\n" % \ + # (imageFormat(texturesDif), texturesDif, + # (imgGamma + imgMap(t_dif)),mappingDif)) + tabWrite("%s \"%s\" \n" % (imageFormat(texturesDif), texturesDif)) + tabWrite("%s\n" % (imgGamma + imgMap(t_dif))) + tabWrite("}\n") + tabWrite("%s\n" % mappingDif) + tabWrite("}\n") + if texturesSpec != "": - # Level 1 is no specular - tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) - + # Level 3 is full specular + tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) 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 != "": + #imageMap = ("{image_map {%s \"%s\" %s }" % \ + # (imageFormat(textures), textures,imgMap(t_dif))) + #file.write("\n\t\t\tuv_mapping pigment %s} %s finish {%s}" % \ + # (imageMap, mapping, safety(material_finish))) + #file.write("\n\t\t\tpigment {uv_mapping image_map " \ + # "{%s \"%s\" %s}%s} finish {%s}" % \ + # (imageFormat(texturesDif), texturesDif,imgMap(t_dif), + # mappingDif, safety(material_finish))) + if texturesNorm != "" and mater.pov.replacement_text == "": ## 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 + # 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 =imgMapTransforms(t_nor) - # 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) + # 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" % \ + 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)) - if texturesSpec != "": + t_nor.normal_factor * 10.0, mappingNor)) + if texturesSpec != "" and mater.pov.replacement_text == "": tabWrite("]\n") - ##################Second index for mapping specular max value############### - tabWrite("[1 \n") - if texturesDif == "" and mater.pov.replacement_text == "": - 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 = imgMapTransforms(t_alpha) - # 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)) - 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") - 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))) - - elif colored_specular_found: - # Level 1 is no specular - tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) - - else: - # Level 2 is translated specular - tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) - - elif mater.pov.replacement_text == "": - mappingDif = imgMapTransforms(t_dif) - # mappingDif = ("scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>" % \ - # ( 1.0 / t_dif.scale.x, - # 1.0 / t_dif.scale.y, - # 1.0 / t_dif.scale.z, - # 0.5-(0.5/t_dif.scale.x) + t_dif.offset.x, - # 0.5-(0.5/t_dif.scale.y) + t_dif.offset.y, - # 0.5-(0.5/t_dif.scale.z) + t_dif.offset.z)) - if texturesAlpha != "": - # Strange that the translation factor for scale is not the same as for - # translate. - # TODO: verify both matches with blender internal. - mappingAlpha = imgMapTransforms(t_alpha) - # 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) - if texturesAlpha and texturesAlpha.startswith("PAT_"): - tabWrite("pigment{pigment_pattern {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)) - tabWrite("pigment_map {\n") - tabWrite("[0 color rgbft<0,0,0,1,1>]\n") - if texturesAlpha and texturesAlpha.startswith("PAT_"): - tabWrite("[1 function{f%s(x,y,z).transmit}]\n" %texturesAlpha) - elif texturesDif and not texturesDif.startswith("PAT_"): - tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \ - (imageFormat(texturesDif), texturesDif, - (imgMap(t_dif) + imgGamma), mappingDif)) - elif texturesDif and texturesDif.startswith("PAT_"): - tabWrite("[1 %s]\n" %texturesDif) - tabWrite("}\n") + #End of slope/ior texture_map + if mater.diffuse_shader == 'MINNAERT' and mater.pov.replacement_text == "": + tabWrite("]\n") tabWrite("}\n") - - else: - if texturesDif and texturesDif.startswith("PAT_"): - tabWrite("pigment{%s}\n" %texturesDif) - else: - tabWrite("pigment {\n") - tabWrite("uv_mapping image_map {\n") - #tabWrite("%s \"%s\" %s}%s\n" % \ - # (imageFormat(texturesDif), texturesDif, - # (imgGamma + imgMap(t_dif)),mappingDif)) - tabWrite("%s \"%s\" \n" % (imageFormat(texturesDif), texturesDif)) - tabWrite("%s\n" % (imgGamma + imgMap(t_dif))) - tabWrite("}\n") - tabWrite("%s\n" % mappingDif) + if mater.diffuse_shader == 'FRESNEL' and mater.pov.replacement_text == "": + c = 1 + while (c <= lampCount): + tabWrite("]\n") tabWrite("}\n") - - if texturesSpec != "": - # Level 3 is full specular - tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) - 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 }" % \ - # (imageFormat(textures), textures,imgMap(t_dif))) - #file.write("\n\t\t\tuv_mapping pigment %s} %s finish {%s}" % \ - # (imageMap, mapping, safety(material_finish))) - #file.write("\n\t\t\tpigment {uv_mapping image_map " \ - # "{%s \"%s\" %s}%s} finish {%s}" % \ - # (imageFormat(texturesDif), texturesDif,imgMap(t_dif), - # mappingDif, safety(material_finish))) - if texturesNorm != "" and mater.pov.replacement_text == "": - ## 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 =imgMapTransforms(t_nor) - # 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.0, mappingNor)) - if texturesSpec != "" and mater.pov.replacement_text == "": - tabWrite("]\n") - - tabWrite("}\n") + c += 1 - #End of slope/ior texture_map - if mater.diffuse_shader == 'MINNAERT' and mater.pov.replacement_text == "": - tabWrite("]\n") + + + # Close first layer of POV "texture" (Blender material) tabWrite("}\n") - if mater.diffuse_shader == 'FRESNEL' and mater.pov.replacement_text == "": - c = 1 - while (c <= lampCount): - tabWrite("]\n") - tabWrite("}\n") - c += 1 - - - - # Close first layer of POV "texture" (Blender material) - tabWrite("}\n") - - if (mater.specular_color.s > 0.0): - colored_specular_found = True - else: - colored_specular_found = False - # Write another layered texture using invisible diffuse and metallic trick - # to emulate colored specular highlights - special_texture_found = False - for t in mater.texture_slots: - if(t and t.use and ((t.texture.type == 'IMAGE' and t.texture.image) or t.texture.type != 'IMAGE') and - (t.use_map_specular or t.use_map_raymir)): - # Specular mapped textures would conflict with colored specular - # because POV can't layer over or under pigment patterned textures - special_texture_found = True - - if colored_specular_found and not special_texture_found: - if comments: - file.write(" // colored highlights with a stransparent metallic layer\n") + if (mater.specular_color.s > 0.0): + colored_specular_found = True else: - tabWrite("\n") - - tabWrite("texture {\n") - tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, 0, 1>}\n" % \ - (mater.specular_color[0], mater.specular_color[1], mater.specular_color[2])) - tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) # Level 2 is translated spec - - texturesNorm = "" + colored_specular_found = False + + # Write another layered texture using invisible diffuse and metallic trick + # to emulate colored specular highlights + special_texture_found = False for t in mater.texture_slots: + if(t and t.use and ((t.texture.type == 'IMAGE' and t.texture.image) or t.texture.type != 'IMAGE') and + (t.use_map_specular or t.use_map_raymir)): + # Specular mapped textures would conflict with colored specular + # because POV can't layer over or under pigment patterned textures + special_texture_found = True + + if colored_specular_found and not special_texture_found: + if comments: + file.write(" // colored highlights with a stransparent metallic layer\n") + else: + tabWrite("\n") + + tabWrite("texture {\n") + tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, 0, 1>}\n" % \ + (mater.specular_color[0], mater.specular_color[1], mater.specular_color[2])) + tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) # Level 2 is translated spec + + texturesNorm = "" + for t in mater.texture_slots: + + if t and t.texture.pov.tex_pattern_type != 'emulator': + proceduralFlag=True + image_filename = string_strip_hyphen(bpy.path.clean_name(t.texture.name)) + if (t and t.texture.type == 'IMAGE' and + t.use and t.texture.image and + t.texture.pov.tex_pattern_type == 'emulator'): + proceduralFlag=False + image_filename = path_image(t.texture.image) + imgGamma = "" + if image_filename: + 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 proceduralFlag: + 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)) + + tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE + + + ################################################################### + index[0] = idx + idx += 1 + - if t and t.texture.pov.tex_pattern_type != 'emulator': - proceduralFlag=True - image_filename = string_strip_hyphen(bpy.path.clean_name(t.texture.name)) - if t and t.texture.type == 'IMAGE' and t.use and t.texture.image and t.texture.pov.tex_pattern_type == 'emulator': - proceduralFlag=False - image_filename = path_image(t.texture.image) - imgGamma = "" - if image_filename: - 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 proceduralFlag: - 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)) - - tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE --MR - - - #################################################################################### - index[0] = idx - idx += 1 - - - - - # Vert Colors - tabWrite("texture_list {\n") - # In case there's is no material slot, give at least one texture (empty so it uses pov default) - if len(vertCols)==0: - file.write(tabStr + "1") - else: - file.write(tabStr + "%s" % (len(vertCols))) # vert count - if material is not None: - if material.pov.replacement_text != "": - file.write("\n") - file.write(" texture{%s}\n" % material.pov.replacement_text) + + # Vert Colors + tabWrite("texture_list {\n") + # In case there's is no material slot, give at least one texture + #(an empty one so it uses pov default) + if len(vertCols)==0: + file.write(tabStr + "1") else: - # Loop through declared materials list - for cMN in LocalMaterialNames: - if material != "Default": - file.write("\n texture{MAT_%s}\n" % cMN)#string_strip_hyphen(materialNames[material])) # Something like that - else: - file.write(" texture{}\n") - tabWrite("}\n") + file.write(tabStr + "%s" % (len(vertCols))) # vert count + + # below "material" alias, changed to ob.active_material + # because variable referenced before assignment + if ob.active_material is not None: + if material.pov.replacement_text != "": + file.write("\n") + file.write(" texture{%s}\n" % material.pov.replacement_text) - # Face indices - tabWrite("face_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: + # Loop through declared materials list + for cMN in LocalMaterialNames: + if material != "Default": + file.write("\n texture{MAT_%s}\n" % cMN) + #use string_strip_hyphen(materialNames[material])) + #or Something like that to clean up the above? else: - indices = ((0, 1, 2),) + file.write(" texture{}\n") + tabWrite("}\n") - if vcol_layer: - col = vcol_layer[fi] + # Face indices + tabWrite("face_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: - cols = col.color1, col.color2, col.color3, col.color4 + indices = (0, 1, 2), (0, 2, 3) 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: - if linebreaksinlists: - 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 + indices = ((0, 1, 2),) - col1 = cols[i1] - col2 = cols[i2] - col3 = cols[i3] + if vcol_layer: + col = vcol_layer[fi] - 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] + if len(fv) == 4: + cols = col.color1, col.color2, col.color3, col.color4 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[:])] + 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: + if linebreaksinlists: + file.write(",\n") + # vert count + file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) else: - diffuse_color = material.diffuse_color[:] - ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ - diffuse_color[2], f.material_index][0] - - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # 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: - if linebreaksinlists: - 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 + file.write(", ") + file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count 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 + 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] + + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ + (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>, %d,%d,%d" % \ + (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count - file.write("\n") - tabWrite("}\n") + file.write("\n") + tabWrite("}\n") - if uv_layer: - tabWrite("uv_indices {\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): @@ -2750,44 +4025,81 @@ def write_pov(filename, scene=None, info_callback=None): 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: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + if me_faces[fi].use_smooth: + if linebreaksinlists: + 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: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + idx = uniqueNormals[faces_normals[fi]][0] + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount + else: + file.write(", ") + file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count file.write("\n") tabWrite("}\n") - if me.materials: - try: - material = me.materials[0] # dodgy - writeObjectMaterial(material, ob) - except IndexError: - print(me) + 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): - #Importance for radiosity sampling added here: - tabWrite("radiosity { \n") - tabWrite("importance %3g \n" % importance) - tabWrite("}\n") + if len(fv) == 4: + indices = (0, 1, 2), (0, 2, 3) + else: + indices = ((0, 1, 2),) - tabWrite("}\n") # End of mesh block + 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: + if linebreaksinlists: + 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])) - bpy.data.meshes.remove(me) + 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 + + bpy.data.meshes.remove(me) for data_name, inst in data_ref.items(): for ob_name, matrix_str in inst: @@ -2839,7 +4151,7 @@ def write_pov(filename, scene=None, info_callback=None): # Commented below was an idea to make the Background image oriented as camera # taken here: -#http://news.povray.org/povray.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.povray.org%3E/ +#http://news.pov.org/pov.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.pov.org%3E/ # Replace 4/3 by the ratio of each image found by some custom or existing # function #mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \ @@ -2862,8 +4174,8 @@ def write_pov(filename, scene=None, info_callback=None): # Further Scale by 2 and translate by -1 are # required for the sky_sphere not to repeat - mappingBlend = "scale 2 scale <%.4g,%.4g,%.4g> translate -1 translate <%.4g,%.4g,%.4g> " \ - "rotate<0,0,0> " % \ + mappingBlend = "scale 2 scale <%.4g,%.4g,%.4g> translate -1 " \ + "translate <%.4g,%.4g,%.4g> rotate<0,0,0> " % \ ((1.0 / t_blend.scale.x), (1.0 / t_blend.scale.y), (1.0 / t_blend.scale.z), @@ -2977,9 +4289,14 @@ def write_pov(filename, scene=None, info_callback=None): # In pov, the scale has reversed influence compared to blender. these number # should correct that tabWrite("mm_per_unit %.6f\n" % \ - (material.subsurface_scattering.scale * 1000.0))# formerly ...scale * (-100.0) + 15.0)) + (material.subsurface_scattering.scale * 1000.0)) + # 1000 rather than scale * (-100.0) + 15.0)) + # In POV-Ray, the scale factor for all subsurface shaders needs to be the same - sslt_samples = (11 - material.subsurface_scattering.error_threshold) * 10 # formerly ...*100 + + # formerly sslt_samples were multiplied by 100 instead of 10 + sslt_samples = (11 - material.subsurface_scattering.error_threshold) * 10 + tabWrite("subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10)) onceSss = 0 @@ -2987,12 +4304,15 @@ def write_pov(filename, scene=None, info_callback=None): tabWrite("ambient_light rgbt<%.3g, %.3g, %.3g,1>\n" % world.ambient_color[:]) onceAmbient = 0 - if (material.pov.refraction_type == "2" or material.pov.photons_reflection == True) and oncePhotons: + if (oncePhotons and + (material.pov.refraction_type == "2" or + material.pov.photons_reflection == True)): tabWrite("photons {\n") tabWrite("spacing %.6f\n" % scene.pov.photon_spacing) tabWrite("max_trace_level %d\n" % scene.pov.photon_max_trace_level) tabWrite("adc_bailout %.3g\n" % scene.pov.photon_adc_bailout) - tabWrite("gather %d, %d\n" % (scene.pov.photon_gather_min, scene.pov.photon_gather_max)) + tabWrite("gather %d, %d\n" % (scene.pov.photon_gather_min, + scene.pov.photon_gather_max)) tabWrite("}\n") oncePhotons = 0 @@ -3032,8 +4352,10 @@ def write_pov(filename, scene=None, info_callback=None): LocalPatternNames = [] for texture in bpy.data.textures: #ok? if texture.users > 0: - currentPatName = string_strip_hyphen(bpy.path.clean_name(texture.name)) #string_strip_hyphen(patternNames[texture.name]) #maybe instead - LocalPatternNames.append(currentPatName) #use this list to prevent writing texture instances several times and assign in mats? + currentPatName = string_strip_hyphen(bpy.path.clean_name(texture.name)) + #string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above + LocalPatternNames.append(currentPatName) + #use above list to prevent writing texture instances several times and assign in mats? file.write("\n #declare PAT_%s = \n" % currentPatName) file.write(exportPattern(texture)) file.write("\n") @@ -3050,9 +4372,21 @@ def write_pov(filename, scene=None, info_callback=None): if comments: file.write("\n//--Lamps--\n\n") - exportLamps([l for l in sel if l.type == 'LAMP']) + exportLamps([L for L in sel if (L.type == 'LAMP' and L.pov.object_as != 'RAINBOW')]) + + if comments: + file.write("\n//--Rainbows--\n\n") + exportRainbows([L for L in sel if (L.type == 'LAMP' and L.pov.object_as == 'RAINBOW')]) + if comments: + file.write("\n//--Special Curves--\n\n") + for c in sel: + if c.type == 'CURVE' and (c.pov.curveshape in {'lathe','sphere_sweep','loft','birail'}): + exportCurves(scene,c) + + + if comments: file.write("\n//--Material Definitions--\n\n") # write a default pigment for objects with no material (comment out to show black) file.write("#default{ pigment{ color rgb 0.8 }}\n") @@ -3065,17 +4399,18 @@ def write_pov(filename, scene=None, info_callback=None): if comments: file.write("\n") - exportMeta([l for l in sel if l.type == 'META']) + exportMeta([m for m in sel if m.type == 'META']) if comments: file.write("//--Mesh objects--\n") exportMeshes(scene, sel) + #What follow used to happen here: #exportCamera() #exportWorld(scene.world) #exportGlobalSettings(scene) - # MR:..and the order was important for an attempt to implement pov 3.7 baking + # MR:..and the order was important for implementing pov 3.7 baking # (mesh camera) comment for the record # CR: Baking should be a special case than. If "baking", than we could change the order. @@ -3172,7 +4507,8 @@ class PovrayRender(bpy.types.RenderEngine): # assume if there is a 64bit binary that the user has a 64bit capable OS if sys.platform[:3] == "win": import winreg - win_reg_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows") + win_reg_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, + "Software\\POV-Ray\\v3.7\\Windows") win_home = winreg.QueryValueEx(win_reg_key, "Home")[0] # First try 64bits UberPOV @@ -3572,8 +4908,9 @@ class PovrayRender(bpy.types.RenderEngine): self._cleanup() - -#################################Operators######################################### +################################################################################## +#################################Operators######################################## +################################################################################## class RenderPovTexturePreview(Operator): bl_idname = "tex.preview_update" bl_label = "Update preview" @@ -3640,9 +4977,11 @@ class RenderPovTexturePreview(Operator): pov_binary = PovrayRender._locate_binary() if sys.platform[:3] == "win": - p1=subprocess.Popen(["%s"%pov_binary,"/EXIT","%s"%iniPrevFile],stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + p1=subprocess.Popen(["%s"%pov_binary,"/EXIT","%s"%iniPrevFile], + stdout=subprocess.PIPE,stderr=subprocess.STDOUT) else: - p1=subprocess.Popen(["%s"%pov_binary,"-d","%s"%iniPrevFile],stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + p1=subprocess.Popen(["%s"%pov_binary,"-d","%s"%iniPrevFile], + stdout=subprocess.PIPE,stderr=subprocess.STDOUT) p1.wait() tex.use_nodes = True @@ -3664,4 +5003,1493 @@ class RenderPovTexturePreview(Operator): links.new(im.outputs[0],previewer.inputs[0]) #tex.type="IMAGE" # makes clip extend possible #tex.extension="CLIP" - return {'FINISHED'}
\ No newline at end of file + return {'FINISHED'} + +#################################POV-Ray specific############################### + +# XXX This should really be in a separate file imho (primitives.py eg?) + +from bpy.props import ( + StringProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + EnumProperty, + PointerProperty, + CollectionProperty, + ) + + +def pov_define_mesh(mesh, verts, edges, faces, name, hide_geometry=True): + if mesh is None: + mesh = bpy.data.meshes.new(name) + mesh.from_pydata(verts, edges, faces) + mesh.update() + mesh.validate(False) # Set it to True to see debug messages (helps ensure you generate valid geometry). + if hide_geometry: + mesh.vertices.foreach_set("hide", [True] * len(mesh.vertices)) + mesh.edges.foreach_set("hide", [True] * len(mesh.edges)) + mesh.polygons.foreach_set("hide", [True] * len(mesh.polygons)) + return mesh + + +class POVRAY_OT_lathe_add(bpy.types.Operator): + bl_idname = "pov.addlathe" + bl_label = "Lathe" + bl_options = {'REGISTER','UNDO'} + bl_description = "adds lathe" + + + def execute(self, context): + layers=[False]*20 + layers[0]=True + bpy.ops.curve.primitive_bezier_curve_add(location=(0, 0, 0), + rotation=(0, 0, 0), layers=layers) + ob=context.scene.objects.active + ob.name = ob.data.name = "PovLathe" + ob.pov.object_as='LATHE' + bpy.ops.object.mode_set(mode='EDIT') + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.transform.rotate(value=-pi/2, axis=(0, 0, 1)) + bpy.ops.object.mode_set(mode='OBJECT') + ob.pov.curveshape = "lathe" + bpy.ops.object.modifier_add(type='SCREW') + bpy.context.object.modifiers["Screw"].axis = 'Y' + bpy.context.object.modifiers["Screw"].show_render = False + return {'FINISHED'} + + + +def pov_superellipsoid_define(context, op, ob): + + if op: + mesh = None + + u = op.se_u + v = op.se_v + n1 = op.se_n1 + n2 = op.se_n2 + edit = op.se_edit + se_param1 = n2 # op.se_param1 + se_param2 = n1 # op.se_param2 + + else: + assert(ob) + mesh = ob.data + + u = ob.pov.se_u + v = ob.pov.se_v + n1 = ob.pov.se_n1 + n2 = ob.pov.se_n2 + edit = ob.pov.se_edit + se_param1 = ob.pov.se_param1 + se_param2 = ob.pov.se_param2 + + verts = [] + r=1 + + stepSegment=360/v*pi/180 + stepRing=pi/u + angSegment=0 + angRing=-pi/2 + + step=0 + for ring in range(0,u-1): + angRing += stepRing + for segment in range(0,v): + step += 1 + angSegment += stepSegment + x = r*(abs(cos(angRing))**n1)*(abs(cos(angSegment))**n2) + if (cos(angRing) < 0 and cos(angSegment) > 0) or \ + (cos(angRing) > 0 and cos(angSegment) < 0): + x = -x + y = r*(abs(cos(angRing))**n1)*(abs(sin(angSegment))**n2) + if (cos(angRing) < 0 and sin(angSegment) > 0) or \ + (cos(angRing) > 0 and sin(angSegment) < 0): + y = -y + z = r*(abs(sin(angRing))**n1) + if sin(angRing) < 0: + z = -z + x = round(x,4) + y = round(y,4) + z = round(z,4) + verts.append((x,y,z)) + if edit == 'TRIANGLES': + verts.append((0,0,1)) + verts.append((0,0,-1)) + + faces = [] + + for i in range(0,u-2): + m=i*v + for p in range(0,v): + if p < v-1: + face=(m+p,1+m+p,v+1+m+p,v+m+p) + if p == v-1: + face=(m+p,m,v+m,v+m+p) + faces.append(face) + if edit == 'TRIANGLES': + indexUp=len(verts)-2 + indexDown=len(verts)-1 + indexStartDown=len(verts)-2-v + for i in range(0,v): + if i < v-1: + face=(indexDown,i,i+1) + faces.append(face) + if i == v-1: + face=(indexDown,i,0) + faces.append(face) + for i in range(0,v): + if i < v-1: + face=(indexUp,i+indexStartDown,i+indexStartDown+1) + faces.append(face) + if i == v-1: + face=(indexUp,i+indexStartDown,indexStartDown) + faces.append(face) + if edit == 'NGONS': + face=[] + for i in range(0,v): + face.append(i) + faces.append(face) + face=[] + indexUp=len(verts)-1 + for i in range(0,v): + face.append(indexUp-i) + faces.append(face) + mesh = pov_define_mesh(mesh, verts, [], faces, "SuperEllipsoid") + + if not ob: + ob_base = object_utils.object_data_add(context, mesh, operator=None) + ob = ob_base.object + #engine = context.scene.render.engine what for? + ob = context.object + ob.name = ob.data.name = "PovSuperellipsoid" + ob.pov.object_as = 'SUPERELLIPSOID' + ob.pov.se_param1 = n2 + ob.pov.se_param2 = n1 + + ob.pov.se_u = u + ob.pov.se_v = v + ob.pov.se_n1 = n1 + ob.pov.se_n2 = n2 + ob.pov.se_edit = edit + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + +class POVRAY_OT_superellipsoid_add(bpy.types.Operator): + bl_idname = "pov.addsuperellipsoid" + bl_label = "Add SuperEllipsoid" + bl_description = "Create a SuperEllipsoid" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + # XXX Keep it in sync with __init__'s RenderPovSettingsConePrimitive + # If someone knows how to define operators' props from a func, I'd be delighted to learn it! + se_param1 = FloatProperty( + name="Parameter 1", + description="", + min=0.00, max=10.0, default=0.04) + + se_param2 = FloatProperty( + name="Parameter 2", + description="", + min=0.00, max=10.0, default=0.04) + + se_u = IntProperty(name = "U-segments", + description = "radial segmentation", + default = 20, min = 4, max = 265) + se_v = IntProperty(name = "V-segments", + description = "lateral segmentation", + default = 20, min = 4, max = 265) + se_n1 = FloatProperty(name = "Ring manipulator", + description = "Manipulates the shape of the Ring", + default = 1.0, min = 0.01, max = 100.0) + se_n2 = FloatProperty(name = "Cross manipulator", + description = "Manipulates the shape of the cross-section", + default = 1.0, min = 0.01, max = 100.0) + se_edit = EnumProperty(items=[("NOTHING", "Nothing", ""), + ("NGONS", "N-Gons", ""), + ("TRIANGLES", "Triangles", "")], + name="Fill up and down", + description="", + default='TRIANGLES') + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + return (engine in cls.COMPAT_ENGINES) + + def execute(self,context): + pov_superellipsoid_define(context, self, None) + + self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + + return {'FINISHED'} + +class POVRAY_OT_superellipsoid_update(bpy.types.Operator): + bl_idname = "pov.superellipsoid_update" + bl_label = "Update" + bl_description = "Update Superellipsoid" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.object.mode_set(mode="OBJECT") + + pov_superellipsoid_define(context, None, context.object) + + return {'FINISHED'} + +def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False): + faces = [] + if not vertIdx1 or not vertIdx2: + return None + if len(vertIdx1) < 2 and len(vertIdx2) < 2: + return None + fan = False + if (len(vertIdx1) != len(vertIdx2)): + if (len(vertIdx1) == 1 and len(vertIdx2) > 1): + fan = True + else: + return None + total = len(vertIdx2) + if closed: + if flipped: + face = [ + vertIdx1[0], + vertIdx2[0], + vertIdx2[total - 1]] + if not fan: + face.append(vertIdx1[total - 1]) + faces.append(face) + + else: + face = [vertIdx2[0], vertIdx1[0]] + if not fan: + face.append(vertIdx1[total - 1]) + face.append(vertIdx2[total - 1]) + faces.append(face) + for num in range(total - 1): + if flipped: + if fan: + face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]] + else: + face = [vertIdx2[num], vertIdx1[num], + vertIdx1[num + 1], vertIdx2[num + 1]] + faces.append(face) + else: + if fan: + face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]] + else: + face = [vertIdx1[num], vertIdx2[num], + vertIdx2[num + 1], vertIdx1[num + 1]] + faces.append(face) + + return faces + +def power(a,b): + if a < 0: + return -((-a)**b) + return a**b + +def supertoroid(R,r,u,v,n1,n2): + a = 2*pi/u + b = 2*pi/v + verts = [] + faces = [] + for i in range(u): + s = power(sin(i*a),n1) + c = power(cos(i*a),n1) + for j in range(v): + c2 = R+r*power(cos(j*b),n2) + s2 = r*power(sin(j*b),n2) + verts.append((c*c2,s*c2,s2))# type as a (mathutils.Vector(c*c2,s*c2,s2))? + if i > 0: + f = createFaces(range((i-1)*v,i*v),range(i*v,(i+1)*v),closed = True) + faces.extend(f) + f = createFaces(range((u-1)*v,u*v),range(v),closed=True) + faces.extend(f) + return verts, faces + +def pov_supertorus_define(context, op, ob): + if op: + mesh = None + st_R = op.st_R + st_r = op.st_r + st_u = op.st_u + st_v = op.st_v + st_n1 = op.st_n1 + st_n2 = op.st_n2 + st_ie = op.st_ie + st_edit = op.st_edit + + else: + assert(ob) + mesh = ob.data + st_R = ob.pov.st_major_radius + st_r = ob.pov.st_minor_radius + st_u = ob.pov.st_u + st_v = ob.pov.st_v + st_n1 = ob.pov.st_ring + st_n2 = ob.pov.st_cross + st_ie = ob.pov.st_ie + st_edit = ob.pov.st_edit + + if st_ie: + rad1 = (st_R+st_r)/2 + rad2 = (st_R-st_r)/2 + if rad2 > rad1: + [rad1,rad2] = [rad2,rad1] + else: + rad1 = st_R + rad2 = st_r + if rad2 > rad1: + rad1 = rad2 + verts,faces = supertoroid(rad1, + rad2, + st_u, + st_v, + st_n1, + st_n2) + mesh = pov_define_mesh(mesh, verts, [], faces, "PovSuperTorus", True) + if not ob: + ob_base = object_utils.object_data_add(context, mesh, operator=None) + + ob = ob_base.object + ob.pov.object_as = 'SUPERTORUS' + ob.pov.st_major_radius = st_R + ob.pov.st_minor_radius = st_r + ob.pov.st_u = st_u + ob.pov.st_v = st_v + ob.pov.st_ring = st_n1 + ob.pov.st_cross = st_n2 + ob.pov.st_ie = st_ie + ob.pov.st_edit = st_edit + +class POVRAY_OT_supertorus_add(bpy.types.Operator): + bl_idname = "pov.addsupertorus" + bl_label = "Add Supertorus" + bl_description = "Create a SuperTorus" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + st_R = FloatProperty(name = "big radius", + description = "The radius inside the tube", + default = 1.0, min = 0.01, max = 100.0) + st_r = FloatProperty(name = "small radius", + description = "The radius of the tube", + default = 0.3, min = 0.01, max = 100.0) + st_u = IntProperty(name = "U-segments", + description = "radial segmentation", + default = 16, min = 3, max = 265) + st_v = IntProperty(name = "V-segments", + description = "lateral segmentation", + default = 8, min = 3, max = 265) + st_n1 = FloatProperty(name = "Ring manipulator", + description = "Manipulates the shape of the Ring", + default = 1.0, min = 0.01, max = 100.0) + st_n2 = FloatProperty(name = "Cross manipulator", + description = "Manipulates the shape of the cross-section", + default = 1.0, min = 0.01, max = 100.0) + st_ie = BoolProperty(name = "Use Int.+Ext. radii", + description = "Use internal and external radii", + default = False) + st_edit = BoolProperty(name="", + description="", + default=False, + options={'HIDDEN'}) + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + return (engine in cls.COMPAT_ENGINES) + + def execute(self, context): + pov_supertorus_define(context, self, None) + + self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + return {'FINISHED'} + +class POVRAY_OT_supertorus_update(bpy.types.Operator): + bl_idname = "pov.supertorus_update" + bl_label = "Update" + bl_description = "Update SuperTorus" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.object.mode_set(mode="OBJECT") + + pov_supertorus_define(context, None, context.object) + + return {'FINISHED'} +######################################################################################################### +class POVRAY_OT_loft_add(bpy.types.Operator): + bl_idname = "pov.addloft" + bl_label = "Add Loft Data" + bl_description = "Create a Curve data for Meshmaker" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + loft_n = IntProperty(name = "Segments", + description = "Vertical segments", + default = 16, min = 3, max = 720) + loft_rings_bottom = IntProperty(name = "Bottom", + description = "Bottom rings", + default = 5, min = 2, max = 100) + loft_rings_side = IntProperty(name = "Side", + description = "Side rings", + default = 10, min = 2, max = 100) + loft_thick = FloatProperty(name = "Thickness", + description = "Manipulates the shape of the Ring", + default = 0.3, min = 0.01, max = 1.0) + loft_r = FloatProperty(name = "Radius", + description = "Radius", + default = 1, min = 0.01, max = 10) + loft_height = FloatProperty(name = "Height", + description = "Manipulates the shape of the Ring", + default = 2, min = 0.01, max = 10.0) + + def execute(self,context): + + props = self.properties + loftData = bpy.data.curves.new('Loft', type='CURVE') + loftData.dimensions = '3D' + loftData.resolution_u = 2 + loftData.show_normal_face = False + n=props.loft_n + thick = props.loft_thick + side = props.loft_rings_side + bottom = props.loft_rings_bottom + h = props.loft_height + r = props.loft_r + distB = r/bottom + r0 = 0.00001 + z = -h/2 + print("New") + for i in range(bottom+1): + coords = [] + angle = 0 + for p in range(n): + x = r0*cos(angle) + y = r0*sin(angle) + coords.append((x,y,z)) + angle+=pi*2/n + r0+=distB + nurbs = loftData.splines.new('NURBS') + nurbs.points.add(len(coords)-1) + for i, coord in enumerate(coords): + x,y,z = coord + nurbs.points[i].co = (x, y, z, 1) + nurbs.use_cyclic_u = True + for i in range(side): + z+=h/side + coords = [] + angle = 0 + for p in range(n): + x = r*cos(angle) + y = r*sin(angle) + coords.append((x,y,z)) + angle+=pi*2/n + nurbs = loftData.splines.new('NURBS') + nurbs.points.add(len(coords)-1) + for i, coord in enumerate(coords): + x,y,z = coord + nurbs.points[i].co = (x, y, z, 1) + nurbs.use_cyclic_u = True + r-=thick + for i in range(side): + coords = [] + angle = 0 + for p in range(n): + x = r*cos(angle) + y = r*sin(angle) + coords.append((x,y,z)) + angle+=pi*2/n + nurbs = loftData.splines.new('NURBS') + nurbs.points.add(len(coords)-1) + for i, coord in enumerate(coords): + x,y,z = coord + nurbs.points[i].co = (x, y, z, 1) + nurbs.use_cyclic_u = True + z-=h/side + z = (-h/2) + thick + distB = (r-0.00001)/bottom + for i in range(bottom+1): + coords = [] + angle = 0 + for p in range(n): + x = r*cos(angle) + y = r*sin(angle) + coords.append((x,y,z)) + angle+=pi*2/n + r-=distB + nurbs = loftData.splines.new('NURBS') + nurbs.points.add(len(coords)-1) + for i, coord in enumerate(coords): + x,y,z = coord + nurbs.points[i].co = (x, y, z, 1) + nurbs.use_cyclic_u = True + ob = bpy.data.objects.new('Loft_shape', loftData) + scn = bpy.context.scene + scn.objects.link(ob) + scn.objects.active = ob + ob.select = True + ob.pov.curveshape = "loft" + return {'FINISHED'} + +class POVRAY_OT_plane_add(bpy.types.Operator): + bl_idname = "pov.addplane" + bl_label = "Plane" + bl_description = "Add Plane" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_plane_add(radius = 100000,layers=layers) + ob = context.object + ob.name = ob.data.name = 'PovInfinitePlane' + bpy.ops.object.mode_set(mode="EDIT") + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.object.shade_smooth() + ob.pov.object_as = "PLANE" + return {'FINISHED'} + +class POVRAY_OT_box_add(bpy.types.Operator): + bl_idname = "pov.addbox" + bl_label = "Box" + bl_description = "Add Box" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_cube_add(layers=layers) + ob = context.object + ob.name = ob.data.name = 'PovBox' + bpy.ops.object.mode_set(mode="EDIT") + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + ob.pov.object_as = "BOX" + return {'FINISHED'} + +class POVRAY_OT_cylinder_add(bpy.types.Operator): + bl_idname = "pov.addcylinder" + bl_label = "Cylinder" + bl_description = "Add Cylinder" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_cylinder_add(layers = layers) + ob = context.object + ob.name = ob.data.name = 'PovCylinder' + bpy.ops.object.mode_set(mode="EDIT") + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + ob.pov.object_as = "CYLINDER" + + return {'FINISHED'} +################################SPHERE########################################## +def pov_sphere_define(context, op, ob, loc): + if op: + R = op.R + + else: + assert(ob) + R = ob.pov.sphere_radius + + #keep object rotation and location for the add object operator + obrot = ob.rotation_euler + #obloc = ob.location + obscale = ob.scale + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, size=ob.pov.sphere_radius, location=loc, rotation=obrot) + #bpy.ops.transform.rotate(axis=obrot,constraint_orientation='GLOBAL') + bpy.ops.transform.resize(value=obscale) + #bpy.ops.transform.rotate(axis=obrot, proportional_size=1) + + + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + #bpy.ops.transform.rotate(axis=obrot,constraint_orientation='GLOBAL') + + if not ob: + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, size=R, location=loc) + ob = context.object + ob.name = ob.data.name = "PovSphere" + ob.pov.object_as = "SPHERE" + ob.pov.sphere_radius = R + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") +class POVRAY_OT_sphere_add(bpy.types.Operator): + bl_idname = "pov.addsphere" + bl_label = "Sphere" + bl_description = "Add Sphere Shape" + bl_options = {'REGISTER', 'UNDO'} + + # XXX Keep it in sync with __init__'s torus Primitive + R = FloatProperty(name="Sphere radius",min=0.00, max=10.0, default=0.5) + + imported_loc = FloatVectorProperty( + name="Imported Pov location", + precision=6, + default=(0.0, 0.0, 0.0)) + + def execute(self,context): + props = self.properties + R = props.R + ob = context.object + if ob: + if ob.pov.imported_loc: + LOC = ob.pov.imported_loc + else: + LOC = bpy.context.scene.cursor_location + pov_sphere_define(context, self, None, LOC) + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + return {'FINISHED'} + + # def execute(self,context): + # layers = 20*[False] + # layers[0] = True + + # bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius, layers=layers) + # ob = context.object + # bpy.ops.object.mode_set(mode="EDIT") + # self.report({'WARNING'}, "This native POV-Ray primitive " + # "won't have any vertex to show in edit mode") + # bpy.ops.mesh.hide(unselected=False) + # bpy.ops.object.mode_set(mode="OBJECT") + # bpy.ops.object.shade_smooth() + # ob.pov.object_as = "SPHERE" + # ob.name = ob.data.name = 'PovSphere' + # return {'FINISHED'} +class POVRAY_OT_sphere_update(bpy.types.Operator): + bl_idname = "pov.sphere_update" + bl_label = "Update" + bl_description = "Update Sphere" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + + pov_sphere_define(context, None, context.object,context.object.location) + + return {'FINISHED'} + + +####################################CONE####################################### +def pov_cone_define(context, op, ob): + verts = [] + faces = [] + if op: + mesh = None + base = op.base + cap = op.cap + seg = op.seg + height = op.height + else: + assert(ob) + mesh = ob.data + base = ob.pov.cone_base_radius + cap = ob.pov.cone_cap_radius + seg = ob.pov.cone_segments + height = ob.pov.cone_height + + zc = height / 2 + zb = -zc + angle = 2 * pi / seg + t = 0 + for i in range(seg): + xb = base * cos(t) + yb = base * sin(t) + xc = cap * cos(t) + yc = cap * sin(t) + verts.append((xb, yb, zb)) + verts.append((xc, yc, zc)) + t += angle + for i in range(seg): + f = i * 2 + if i == seg - 1: + faces.append([0, 1, f + 1, f]) + else: + faces.append([f + 2, f + 3, f + 1, f]) + if base != 0: + base_face = [] + for i in range(seg - 1, -1, -1): + p = i * 2 + base_face.append(p) + faces.append(base_face) + if cap != 0: + cap_face = [] + for i in range(seg): + p = i * 2 + 1 + cap_face.append(p) + faces.append(cap_face) + + mesh = pov_define_mesh(mesh, verts, [], faces, "PovCone", True) + if not ob: + ob_base = object_utils.object_data_add(context, mesh, operator=None) + ob = ob_base.object + ob.pov.object_as = "CONE" + ob.pov.cone_base_radius = base + ob.pov.cone_cap_radius = cap + ob.pov.cone_height = height + ob.pov.cone_base_z = zb + ob.pov.cone_cap_z = zc + + +class POVRAY_OT_cone_add(bpy.types.Operator): + bl_idname = "pov.cone_add" + bl_label = "Cone" + bl_description = "Add Cone" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + # XXX Keep it in sync with __init__'s RenderPovSettingsConePrimitive + # If someone knows how to define operators' props from a func, I'd be delighted to learn it! + base = FloatProperty( + name = "Base radius", description = "The first radius of the cone", + default = 1.0, min = 0.01, max = 100.0) + cap = FloatProperty( + name = "Cap radius", description = "The second radius of the cone", + default = 0.3, min = 0.0, max = 100.0) + seg = IntProperty( + name = "Segments", description = "Radial segmentation of the proxy mesh", + default = 16, min = 3, max = 265) + height = FloatProperty( + name = "Height", description = "Height of the cone", + default = 2.0, min = 0.01, max = 100.0) + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + return (engine in cls.COMPAT_ENGINES) + + def execute(self, context): + pov_cone_define(context, self, None) + + self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + return {'FINISHED'} + + +class POVRAY_OT_cone_update(bpy.types.Operator): + bl_idname = "pov.cone_update" + bl_label = "Update" + bl_description = "Update Cone" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.object.mode_set(mode="OBJECT") + + pov_cone_define(context, None, context.object) + + return {'FINISHED'} +######################################################################################################### + +class POVRAY_OT_isosurface_box_add(bpy.types.Operator): + bl_idname = "pov.addisosurfacebox" + bl_label = "Isosurface Box" + bl_description = "Add Isosurface contained by Box" + bl_options = {'REGISTER', 'UNDO'} + + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_cube_add(layers = layers) + ob = context.object + bpy.ops.object.mode_set(mode="EDIT") + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + ob.pov.object_as = "ISOSURFACE" + ob.pov.contained_by = 'box' + ob.name = 'Isosurface' + return {'FINISHED'} + +class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator): + bl_idname = "pov.addisosurfacesphere" + bl_label = "Isosurface Sphere" + bl_description = "Add Isosurface contained by Sphere" + bl_options = {'REGISTER', 'UNDO'} + + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4,layers=layers) + ob = context.object + bpy.ops.object.mode_set(mode="EDIT") + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.object.shade_smooth() + ob.pov.object_as = "ISOSURFACE" + ob.pov.contained_by = 'sphere' + ob.name = 'Isosurface' + return {'FINISHED'} + +class POVRAY_OT_sphere_sweep_add(bpy.types.Operator): + bl_idname = "pov.addspheresweep" + bl_label = "Sphere Sweep" + bl_description = "Create Sphere Sweep along curve" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.curve.primitive_nurbs_curve_add(layers = layers) + ob = context.object + ob.name = ob.data.name = "PovSphereSweep" + ob.pov.curveshape = "sphere_sweep" + ob.data.bevel_depth = 0.02 + ob.data.bevel_resolution = 4 + ob.data.fill_mode = 'FULL' + #ob.data.splines[0].order_u = 4 + + return {'FINISHED'} + +class POVRAY_OT_blob_add(bpy.types.Operator): + bl_idname = "pov.addblobsphere" + bl_label = "Blob Sphere" + bl_description = "Add Blob Sphere" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + layers = 20*[False] + layers[0] = True + bpy.ops.object.metaball_add(type = 'BALL',layers = layers) + ob = context.object + ob.name = "Blob" + return {'FINISHED'} + + +class POVRAY_OT_rainbow_add(bpy.types.Operator): + bl_idname = "pov.addrainbow" + bl_label = "Rainbow" + bl_description = "Add Rainbow" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + cam = context.scene.camera + bpy.ops.object.lamp_add(type='SPOT', radius=1) + ob = context.object + ob.data.show_cone = False + ob.data.spot_blend = 0.5 + ob.data.shadow_buffer_clip_end = 0 + ob.data.shadow_buffer_clip_start = 4*cam.location.length + ob.data.distance = cam.location.length + ob.data.energy = 0 + ob.name = ob.data.name = "PovRainbow" + ob.pov.object_as = "RAINBOW" + + #obj = context.object + bpy.ops.object.constraint_add(type='DAMPED_TRACK') + + + + ob.constraints["Damped Track"].target = cam + ob.constraints["Damped Track"].track_axis = 'TRACK_NEGATIVE_Z' + ob.location = -cam.location + + #refocus on the actual rainbow + bpy.context.scene.objects.active = ob + ob.select=True + + return {'FINISHED'} + +class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper): + bl_idname = "pov.addheightfield" + bl_label = "Height Field" + bl_description = "Add Height Field " + bl_options = {'REGISTER', 'UNDO'} + + # XXX Keep it in sync with __init__'s hf Primitive + # filename_ext = ".png" + + # filter_glob = StringProperty( + # default="*.exr;*.gif;*.hdr;*.iff;*.jpeg;*.jpg;*.pgm;*.png;*.pot;*.ppm;*.sys;*.tga;*.tiff;*.EXR;*.GIF;*.HDR;*.IFF;*.JPEG;*.JPG;*.PGM;*.PNG;*.POT;*.PPM;*.SYS;*.TGA;*.TIFF", + # options={'HIDDEN'}, + # ) + quality = IntProperty(name = "Quality", + description = "", + default = 100, min = 1, max = 100) + hf_filename = StringProperty(maxlen = 1024) + + hf_gamma = FloatProperty( + name="Gamma", + description="Gamma", + min=0.0001, max=20.0, default=1.0) + + hf_premultiplied = BoolProperty( + name="Premultiplied", + description="Premultiplied", + default=True) + + hf_smooth = BoolProperty( + name="Smooth", + description="Smooth", + default=False) + + hf_water = FloatProperty( + name="Water Level", + description="Wather Level", + min=0.00, max=1.00, default=0.0) + + hf_hierarchy = BoolProperty( + name="Hierarchy", + description="Height field hierarchy", + default=True) + def execute(self,context): + props = self.properties + impath = bpy.path.abspath(self.filepath) + img = bpy.data.images.load(impath) + im_name = img.name + im_name, file_extension = os.path.splitext(im_name) + hf_tex = bpy.data.textures.new('%s_hf_image'%im_name, type = 'IMAGE') + hf_tex.image = img + mat = bpy.data.materials.new('Tex_%s_hf'%im_name) + hf_slot = mat.texture_slots.create(-1) + hf_slot.texture = hf_tex + layers = 20*[False] + layers[0] = True + quality = props.quality + res = 100/quality + w,h = hf_tex.image.size[:] + w = int(w/res) + h = int(h/res) + bpy.ops.mesh.primitive_grid_add(x_subdivisions=w, y_subdivisions=h,radius = 0.5,layers=layers) + ob = context.object + ob.name = ob.data.name = '%s'%im_name + ob.data.materials.append(mat) + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.noise(factor=1) + bpy.ops.object.mode_set(mode="OBJECT") + + #needs a loop to select by index? + #bpy.ops.object.material_slot_remove() + #material just left there for now + + + mat.texture_slots.clear(-1) + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + ob.pov.object_as = 'HEIGHT_FIELD' + ob.pov.hf_filename = impath + return {'FINISHED'} + + +############################TORUS############################################ +def pov_torus_define(context, op, ob): + if op: + mas = op.mas + mis = op.mis + mar = op.mar + mir = op.mir + else: + assert(ob) + mas = ob.pov.torus_major_segments + mis = ob.pov.torus_minor_segments + mar = ob.pov.torus_major_radius + mir = ob.pov.torus_minor_radius + + #keep object rotation and location for the add object operator + obrot = ob.rotation_euler + obloc = ob.location + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.mesh.primitive_torus_add(rotation = obrot, location = obloc, major_segments=mas, minor_segments=mis,major_radius=mar, minor_radius=mir) + + + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + + + if not ob: + bpy.ops.mesh.primitive_torus_add(major_segments=mas, minor_segments=mis,major_radius=mar, minor_radius=mir) + ob = context.object + ob.name = ob.data.name = "PovTorus" + ob.pov.object_as = "TORUS" + ob.pov.torus_major_segments = mas + ob.pov.torus_minor_segments = mis + ob.pov.torus_major_radius = mar + ob.pov.torus_minor_radius = mir + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + +class POVRAY_OT_torus_add(bpy.types.Operator): + bl_idname = "pov.addtorus" + bl_label = "Torus" + bl_description = "Add Torus" + bl_options = {'REGISTER', 'UNDO'} + + # XXX Keep it in sync with __init__'s torus Primitive + mas = IntProperty(name = "Major Segments", + description = "", + default = 48, min = 3, max = 720) + mis = IntProperty(name = "Minor Segments", + description = "", + default = 12, min = 3, max = 720) + mar = FloatProperty(name = "Major Radius", + description = "", + default = 1.0) + mir = FloatProperty(name = "Minor Radius", + description = "", + default = 0.25) + def execute(self,context): + props = self.properties + mar = props.mar + mir = props.mir + mas = props.mas + mis = props.mis + pov_torus_define(context, self, None) + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + return {'FINISHED'} + + +class POVRAY_OT_torus_update(bpy.types.Operator): + bl_idname = "pov.torus_update" + bl_label = "Update" + bl_description = "Update Torus" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + + pov_torus_define(context, None, context.object) + + return {'FINISHED'} + +################################################################################### + + +class POVRAY_OT_prism_add(bpy.types.Operator): + bl_idname = "pov.addprism" + bl_label = "Prism" + bl_description = "Create Prism" + bl_options = {'REGISTER', 'UNDO'} + + prism_n = IntProperty(name = "Sides", + description = "Number of sides", + default = 5, min = 3, max = 720) + prism_r = FloatProperty(name = "Radius", + description = "Radius", + default = 1.0) + def execute(self,context): + + props = self.properties + loftData = bpy.data.curves.new('Prism', type='CURVE') + loftData.dimensions = '2D' + loftData.resolution_u = 2 + loftData.show_normal_face = False + loftData.extrude = 2 + n=props.prism_n + r=props.prism_r + coords = [] + z = 0 + angle = 0 + for p in range(n): + x = r*cos(angle) + y = r*sin(angle) + coords.append((x,y,z)) + angle+=pi*2/n + poly = loftData.splines.new('POLY') + poly.points.add(len(coords)-1) + for i, coord in enumerate(coords): + x,y,z = coord + poly.points[i].co = (x, y, z, 1) + poly.use_cyclic_u = True + + ob = bpy.data.objects.new('Prism_shape', loftData) + scn = bpy.context.scene + scn.objects.link(ob) + scn.objects.active = ob + ob.select = True + ob.pov.curveshape = "prism" + ob.name = ob.data.name = "Prism" + return {'FINISHED'} + +##############################PARAMETRIC###################################### +def pov_parametric_define(context, op, ob): + if op: + u_min = op.u_min + u_max = op.u_max + v_min = op.v_min + v_max = op.v_max + x_eq = op.x_eq + y_eq = op.y_eq + z_eq = op.z_eq + + else: + assert(ob) + u_min = ob.pov.u_min + u_max = ob.pov.u_max + v_min = ob.pov.v_min + v_max = ob.pov.v_max + x_eq = ob.pov.x_eq + y_eq = ob.pov.y_eq + z_eq = ob.pov.z_eq + + #keep object rotation and location for the updated object + obloc = ob.location + obrot = ob.rotation_euler # In radians + #Parametric addon has no loc rot, some extra work is needed + #in case cursor has moved + curloc = bpy.context.scene.cursor_location + + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.reveal() + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete(type='VERT') + bpy.ops.mesh.primitive_xyz_function_surface(x_eq=x_eq, y_eq=y_eq, z_eq=z_eq, range_u_min=u_min, range_u_max=u_max, range_v_min=v_min, range_v_max=v_max) + bpy.ops.mesh.select_all(action='SELECT') + #extra work: + bpy.ops.transform.translate(value=(obloc-curloc), proportional_size=1) + bpy.ops.transform.rotate(axis=obrot, proportional_size=1) + + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + + + if not ob: + bpy.ops.mesh.primitive_xyz_function_surface(x_eq=x_eq, y_eq=y_eq, z_eq=z_eq, range_u_min=u_min, range_u_max=u_max, range_v_min=v_min, range_v_max=v_max) + ob = context.object + ob.name = ob.data.name = "PovParametric" + ob.pov.object_as = "PARAMETRIC" + + ob.pov.u_min = u_min + ob.pov.u_max = u_max + ob.pov.v_min = v_min + ob.pov.v_max = v_max + ob.pov.x_eq = x_eq + ob.pov.y_eq = y_eq + ob.pov.z_eq = z_eq + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") +class POVRAY_OT_parametric_add(bpy.types.Operator): + bl_idname = "pov.addparametric" + bl_label = "Parametric" + bl_description = "Add Paramertic" + bl_options = {'REGISTER', 'UNDO'} + + # XXX Keep it in sync with __init__'s Parametric primitive + u_min = FloatProperty(name = "U Min", + description = "", + default = 0.0) + v_min = FloatProperty(name = "V Min", + description = "", + default = 0.0) + u_max = FloatProperty(name = "U Max", + description = "", + default = 6.28) + v_max = FloatProperty(name = "V Max", + description = "", + default = 12.57) + x_eq = StringProperty( + maxlen=1024, default = "cos(v)*(1+cos(u))*sin(v/8)") + y_eq = StringProperty( + maxlen=1024, default = "sin(u)*sin(v/8)+cos(v/8)*1.5") + z_eq = StringProperty( + maxlen=1024, default = "sin(v)*(1+cos(u))*sin(v/8)") + + def execute(self,context): + props = self.properties + u_min = props.u_min + v_min = props.v_min + u_max = props.u_max + v_max = props.v_max + x_eq = props.x_eq + y_eq = props.y_eq + z_eq = props.z_eq + + pov_parametric_define(context, self, None) + self.report({'WARNING'}, "This native POV-Ray primitive " + "won't have any vertex to show in edit mode") + return {'FINISHED'} + +class POVRAY_OT_parametric_update(bpy.types.Operator): + bl_idname = "pov.parametric_update" + bl_label = "Update" + bl_description = "Update parametric object" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + ob = context.object + return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES) + + def execute(self, context): + + pov_parametric_define(context, None, context.object) + + return {'FINISHED'} +####################################################################### +class POVRAY_OT_shape_polygon_to_circle_add(bpy.types.Operator): + bl_idname = "pov.addpolygontocircle" + bl_label = "Polygon To Circle Blending" + bl_description = "Add Polygon To Circle Blending Surface" + bl_options = {'REGISTER', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + # XXX Keep it in sync with __init__'s polytocircle properties + polytocircle_resolution = IntProperty(name = "Resolution", + description = "", + default = 3, min = 0, max = 256) + polytocircle_ngon = IntProperty(name = "NGon", + description = "", + min = 3, max = 64,default = 5) + polytocircle_ngonR = FloatProperty(name = "NGon Radius", + description = "", + default = 0.3) + polytocircle_circleR = FloatProperty(name = "Circle Radius", + description = "", + default = 1.0) + def execute(self,context): + props = self.properties + ngon = props.polytocircle_ngon + ngonR = props.polytocircle_ngonR + circleR = props.polytocircle_circleR + resolution = props.polytocircle_resolution + layers = 20*[False] + layers[0] = True + bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='NGON',enter_editmode=True, layers=layers) + bpy.ops.transform.translate(value=(0, 0, 1)) + bpy.ops.mesh.subdivide(number_cuts=resolution) + numCircleVerts = ngon + (ngon*resolution) + bpy.ops.mesh.select_all(action='DESELECT') + bpy.ops.mesh.primitive_circle_add(vertices=numCircleVerts, radius=circleR, fill_type='NGON',enter_editmode=True, layers=layers) + bpy.ops.transform.translate(value=(0, 0, -1)) + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.bridge_edge_loops() + if ngon < 5: + bpy.ops.mesh.select_all(action='DESELECT') + bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='TRIFAN',enter_editmode=True, layers=layers) + bpy.ops.transform.translate(value=(0, 0, 1)) + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.remove_doubles() + bpy.ops.object.mode_set(mode='OBJECT') + ob = context.object + ob.name = "Polygon_To_Circle" + ob.pov.object_as = 'POLYCIRCLE' + ob.pov.ngon = ngon + ob.pov.ngonR = ngonR + ob.pov.circleR = circleR + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.hide(unselected=False) + bpy.ops.object.mode_set(mode="OBJECT") + return {'FINISHED'} + +#############################IMPORT +class ImportAvogadroPOV(bpy.types.Operator, ImportHelper): + """Load Povray File as output by Avogadro""" + bl_idname = "import_scene.avogadro" + bl_label = "Import POV Avogadro" + bl_options = {'PRESET', 'UNDO'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + filename_ext = ".pov" + filter_glob = StringProperty( + default="*.pov", + options={'HIDDEN'}, + ) + + def execute(self, context): + coords=[] + colors = [] + matNames = [] + xall = yall = zall = [] + layers = 20*[False] + layers[0] = True + ob = None + camloc = (0,0,0) + filepov = bpy.path.abspath(self.filepath) + for line in open(filepov): + string = line.replace("<"," ") + chars = [">","{","}",","] + for symbol in chars: + string = string.replace(symbol," ") + split = string.split() + if split and split[0] == "location": + x = float(split[1]) + y = float(split[2]) + z = float(split[3]) + camloc = ((x,y,z)) + if split and len(split) == 7: + try: + x1 = float(split[0]) + coords.append(x1) + except: + pass + if coords != []: + x1 = float(split[0]) + y1 = float(split[1]) + z1 = float(split[2]) + x2 = float(split[3]) + y2 = float(split[4]) + z2 = float(split[5]) + xall.append(x1) + yall.append(y1) + zall.append(z1) + xall.append(x2) + yall.append(y2) + zall.append(z2) + radius = float(split[6]) + curveData = bpy.data.curves.new('myCurve', type='CURVE') + curveData.dimensions = '3D' + curveData.resolution_u = 2 + curveData.fill_mode = "FULL" + curveData.bevel_depth = radius + curveData.bevel_resolution = 5 + polyline = curveData.splines.new('POLY') + polyline.points.add(1) + polyline.points[0].co = (x1, y1, z1, 1) + polyline.points[1].co = (x2, y2, z2, 1) + ob = bpy.data.objects.new('myCurve', curveData) + scn = bpy.context.scene + scn.objects.link(ob) + scn.objects.active = ob + ob.select = True + bpy.ops.object.convert(target='MESH',keep_original=False) + #XXX TODO use a PovCylinder instead of mesh + #but add end points and radius to addPovcylinder op first + ob.select=False + coords = [] + if split and len(split) == 4: + try: + x = float(split[0]) + coords.append(x) + except: + pass + if coords != []: + x = float(split[0]) + y = float(split[1]) + z = float(split[2]) + xall.append(x) + yall.append(y) + zall.append(z) + radius = float(split[3]) + + + ob.pov.imported_loc=(x, y, z) + bpy.ops.pov.addsphere(R=radius, imported_loc=(x, y, z)) + bpy.ops.object.shade_smooth() + ob = bpy.context.object + coords = [] + if split and len(split) == 6: + if split[0] == "pigment": + r,g,b,t = float(split[2]),float(split[3]),float(split[4]),float(split[5]) + color = (r,g,b,t) + if colors == [] or (colors != [] and color not in colors): + colors.append(color) + name = ob.name+"_mat" + matNames.append(name) + mat = bpy.data.materials.new(name) + mat.diffuse_color = (r,g,b) + mat.alpha = 1-t + ob.data.materials.append(mat) + print (colors) + else: + for i in range(len(colors)): + if color == colors[i]: + ob.data.materials.append(bpy.data.materials[matNames[i]]) + x0 = min(xall) + x1 = max(xall) + y0 = min(yall) + y1 = max(yall) + z0 = min(zall) + z1 = max(zall) + x = (x0+x1)/2 + y = (y0+y1)/2 + z = (z0+z1)/2 + bpy.ops.object.empty_add(layers=layers) + ob = bpy.context.object + ob.location = ((x,y,z)) + for obj in bpy.context.scene.objects: + if obj.type == "CAMERA": + track = obj.constraints.new(type = "TRACK_TO") + track.target = ob + track.track_axis ="TRACK_NEGATIVE_Z" + track.up_axis = "UP_Y" + obj.location = camloc + for obj in bpy.context.scene.objects: + if obj.type == "LAMP": + obj.location = camloc + obj.pov.light_type = "shadowless" + break + return {'FINISHED'}
\ No newline at end of file diff --git a/render_povray/ui.py b/render_povray/ui.py index 2d0b1099..f5ce2602 100644 --- a/render_povray/ui.py +++ b/render_povray/ui.py @@ -29,6 +29,7 @@ properties_render.RENDER_PT_shading.COMPAT_ENGINES.add('POVRAY_RENDER') properties_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER') del properties_render + # Use only a subset of the world panels from bl_ui import properties_world properties_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER') @@ -37,25 +38,8 @@ properties_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER') properties_world.WORLD_PT_mist.COMPAT_ENGINES.add('POVRAY_RENDER') del properties_world -# Example of wrapping every class 'as is' -from bl_ui import properties_material -for member in dir(properties_material): - subclass = getattr(properties_material, member) - try: - subclass.COMPAT_ENGINES.add('POVRAY_RENDER') - except: - pass -del properties_material - -from bl_ui import properties_data_mesh -for member in dir(properties_data_mesh): - subclass = getattr(properties_data_mesh, member) - try: - subclass.COMPAT_ENGINES.add('POVRAY_RENDER') - except: - pass -del properties_data_mesh +# Example of wrapping every class 'as is' from bl_ui import properties_texture from bl_ui.properties_texture import context_tex_datablock for member in dir(properties_texture): @@ -67,6 +51,20 @@ for member in dir(properties_texture): del properties_texture +# Example of wrapping every class 'as is' except some +from bl_ui import properties_material +for member in dir(properties_material): + subclass = getattr(properties_material, member) + if subclass not in (properties_material.MATERIAL_PT_transp_game, + properties_material.MATERIAL_PT_game_settings, + properties_material.MATERIAL_PT_physics): + try: + subclass.COMPAT_ENGINES.add('POVRAY_RENDER') + except: + pass +del properties_material + + from bl_ui import properties_data_camera for member in dir(properties_data_camera): subclass = getattr(properties_data_camera, member) @@ -76,14 +74,8 @@ for member in dir(properties_data_camera): pass del properties_data_camera -from bl_ui import properties_data_lamp -for member in dir(properties_data_lamp): - subclass = getattr(properties_data_lamp, member) - try: - subclass.COMPAT_ENGINES.add('POVRAY_RENDER') - except: - 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 @@ -94,7 +86,6 @@ for member in dir(properties_particle): # add all "particle" panels from blende pass del properties_particle - class RenderButtonsPanel(): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -153,7 +144,6 @@ class ObjectButtonsPanel(): rd = context.scene.render return obj and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) - class CameraDataButtonsPanel(): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -190,7 +180,217 @@ class TextButtonsPanel(): rd = context.scene.render return text and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) +from bl_ui import properties_data_mesh +# These panels are kept +properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add('POVRAY_RENDER') +properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add('POVRAY_RENDER') + +## make some native panels contextual to some object variable +## by recreating custom panels inheriting their properties + +class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel): + COMPAT_ENGINES = {'POVRAY_RENDER'} + POV_OBJECT_TYPES = {'PLANE', 'BOX', 'SPHERE', 'CYLINDER', 'CONE', 'TORUS', 'BLOB', + 'ISOSURFACE', 'SUPERELLIPSOID', 'SUPERTORUS', 'HEIGHT_FIELD', + 'PARAMETRIC', 'POLYCIRCLE'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + # We use our parent class poll func too, avoids to re-define too much things... + return (super(PovDataButtonsPanel, cls).poll(context) and + obj and obj.pov.object_as not in cls.POV_OBJECT_TYPES) + + +# We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups). +# Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work. +# So we simply have to explicitly copy here the interesting bits. ;) +class DATA_PT_POV_normals(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_normals.bl_label + + draw = properties_data_mesh.DATA_PT_normals.draw + + +class DATA_PT_POV_texture_space(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_texture_space.bl_label + bl_options = properties_data_mesh.DATA_PT_texture_space.bl_options + + draw = properties_data_mesh.DATA_PT_texture_space.draw + + +class DATA_PT_POV_vertex_groups(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_vertex_groups.bl_label + + draw = properties_data_mesh.DATA_PT_vertex_groups.draw + + +class DATA_PT_POV_shape_keys(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_shape_keys.bl_label + + draw = properties_data_mesh.DATA_PT_shape_keys.draw + + +class DATA_PT_uv_texture(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_uv_texture.bl_label + + draw = properties_data_mesh.DATA_PT_uv_texture.draw + + +class DATA_PT_POV_vertex_colors(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_vertex_colors.bl_label + + draw = properties_data_mesh.DATA_PT_vertex_colors.draw + + +class DATA_PT_POV_customdata(PovDataButtonsPanel, bpy.types.Panel): + bl_label = properties_data_mesh.DATA_PT_customdata.bl_label + bl_options = properties_data_mesh.DATA_PT_customdata.bl_options + draw = properties_data_mesh.DATA_PT_customdata.draw + + + +del properties_data_mesh + + +################################################################################ +# from bl_ui import properties_data_lamp +# for member in dir(properties_data_lamp): + # subclass = getattr(properties_data_lamp, member) + # try: + # subclass.COMPAT_ENGINES.add('POVRAY_RENDER') + # except: + # pass +# del properties_data_lamp +#########################LAMPS################################ + +from bl_ui import properties_data_lamp + +# These panels are kept +properties_data_lamp.DATA_PT_custom_props_lamp.COMPAT_ENGINES.add('POVRAY_RENDER') +properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('POVRAY_RENDER') + +## make some native panels contextual to some object variable +## by recreating custom panels inheriting their properties +class PovLampButtonsPanel(properties_data_lamp.DataButtonsPanel): + COMPAT_ENGINES = {'POVRAY_RENDER'} + POV_OBJECT_TYPES = {'RAINBOW'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + # We use our parent class poll func too, avoids to re-define too much things... + return (super(PovLampButtonsPanel, cls).poll(context) and + obj and obj.pov.object_as not in cls.POV_OBJECT_TYPES) + + +# We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups). +# Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work. +# So we simply have to explicitly copy here the interesting bits. ;) + +class LAMP_PT_POV_preview(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_preview.bl_label + + draw = properties_data_lamp.DATA_PT_preview.draw + +class LAMP_PT_POV_lamp(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_lamp.bl_label + + draw = properties_data_lamp.DATA_PT_lamp.draw + +class LAMP_PT_POV_sunsky(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_sunsky.bl_label + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.scene.render.engine + return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES) + + draw = properties_data_lamp.DATA_PT_sunsky.draw + +class LAMP_PT_POV_shadow(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_shadow.bl_label + + draw = properties_data_lamp.DATA_PT_shadow.draw + +class LAMP_PT_POV_area(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_area.bl_label + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.scene.render.engine + return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES) + + draw = properties_data_lamp.DATA_PT_area.draw +class LAMP_PT_POV_spot(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_spot.bl_label + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.scene.render.engine + return (lamp and lamp.type == 'SPOT') and (engine in cls.COMPAT_ENGINES) + draw = properties_data_lamp.DATA_PT_spot.draw + +class LAMP_PT_POV_falloff_curve(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_lamp.DATA_PT_falloff_curve.bl_label + bl_options = properties_data_lamp.DATA_PT_falloff_curve.bl_options + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.scene.render.engine + + return (lamp and lamp.type in {'POINT', 'SPOT'} and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES) + draw = properties_data_lamp.DATA_PT_falloff_curve.draw + +class OBJECT_PT_povray_obj_rainbow(PovLampButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Rainbow" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'RAINBOW' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'RAINBOW': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Rainbow projection angle: " + str(obj.data.spot_size)) + col.label(text="Rainbow width: " + str(obj.data.spot_blend)) + col.label(text="Rainbow distance: " + str(obj.data.shadow_buffer_clip_start)) + col.label(text="Rainbow arc angle: " + str(obj.pov.arc_angle)) + col.label(text="Rainbow falloff angle: " + str(obj.pov.falloff_angle)) + + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.cone_update", text="Update",icon="MESH_CONE") + + #col.label(text="Parameters:") + col.prop(obj.data, "spot_size", text="Rainbow Projection Angle") + col.prop(obj.data, "spot_blend", text="Rainbow width") + col.prop(obj.data, "shadow_buffer_clip_start", text="Visibility distance") + col.prop(obj.pov, "arc_angle") + col.prop(obj.pov, "falloff_angle") + +del properties_data_lamp +############################################################################### + class RENDER_PT_povray_export_settings(RenderButtonsPanel, bpy.types.Panel): bl_label = "Export Settings" COMPAT_ENGINES = {'POVRAY_RENDER'} @@ -267,9 +467,11 @@ class RENDER_PT_povray_antialias(RenderButtonsPanel, bpy.types.Panel): bl_label = "Anti-Aliasing" COMPAT_ENGINES = {'POVRAY_RENDER'} + def draw_header(self, context): + prefs = bpy.context.user_preferences.addons[__package__].preferences scene = context.scene - if bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method =='2': + if prefs.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method == '2': self.layout.prop(scene.pov, "antialias_enable", text="", icon='ERROR') elif scene.pov.antialias_enable: self.layout.prop(scene.pov, "antialias_enable", text="", icon='ANTIALIASED') @@ -277,16 +479,16 @@ class RENDER_PT_povray_antialias(RenderButtonsPanel, bpy.types.Panel): self.layout.prop(scene.pov, "antialias_enable", text="", icon='ALIASED') def draw(self, context): + prefs = bpy.context.user_preferences.addons[__package__].preferences layout = self.layout - scene = context.scene - + layout.active = scene.pov.antialias_enable - row = layout.row() row.prop(scene.pov, "antialias_method", text="") - if bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method =='2': + + if prefs.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method == '2': col = layout.column() col.alignment = 'CENTER' col.label(text="Stochastic Anti Aliasing is") @@ -309,11 +511,11 @@ class RENDER_PT_povray_antialias(RenderButtonsPanel, bpy.types.Panel): row = layout.row() row.prop(scene.pov, "antialias_threshold", text="AA Threshold") row.prop(scene.pov, "antialias_gamma", text="AA Gamma") - - if bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray == 'uberpov': + + if prefs.branch_feature_set_povray == 'uberpov': row = layout.row() row.prop(scene.pov, "antialias_confidence", text="AA Confidence") - if scene.pov.antialias_method =='2': + if scene.pov.antialias_method == '2': row.enabled = True else: row.enabled = False @@ -691,22 +893,26 @@ class TEXTURE_PT_povray_parameters(TextureButtonsPanel, bpy.types.Panel): "f_quartic_saddle","f_sphere","f_steiners_roman", "f_torus_gumdrop","f_umbrella"}: func = 1 - if tex.pov.func_list in {"f_bicorn","f_bifolia","f_boy_surface","f_superellipsoid","f_torus"}: + if tex.pov.func_list in {"f_bicorn","f_bifolia","f_boy_surface","f_superellipsoid", + "f_torus"}: func = 2 if tex.pov.func_list in {"f_ellipsoid","f_folium_surface","f_hyperbolic_torus", "f_kampyle_of_eudoxus","f_parabolic_torus", "f_quartic_cylinder","f_torus2"}: func = 3 if tex.pov.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"}: + "f_isect_ellipsoids","f_kummer_surface_v2", + "f_ovals_of_cassini","f_rounded_box","f_spikes_2d", + "f_strophoid"}: func = 4 - if tex.pov.func_list in {"f_algbr_cyl1","f_algbr_cyl2","f_algbr_cyl3","f_algbr_cyl4", - "f_blob","f_mesh1","f_poly4","f_spikes"}: + if tex.pov.func_list in {"f_algbr_cyl1","f_algbr_cyl2","f_algbr_cyl3", + "f_algbr_cyl4","f_blob","f_mesh1","f_poly4","f_spikes"}: func = 5 - if tex.pov.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"}: + if tex.pov.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"}: func = 6 if tex.pov.func_list in {"f_helix1","f_helix2","f_piriform_2d","f_strophoid_2d"}: func = 7 @@ -844,6 +1050,249 @@ class OBJECT_PT_povray_obj_importance(ObjectButtonsPanel, bpy.types.Panel): col.prop(obj.pov, "spacing_multiplier", text="Photons Spacing Multiplier") +class OBJECT_PT_povray_obj_sphere(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Sphere" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'SPHERE' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'SPHERE': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Sphere radius: " + str(obj.pov.sphere_radius)) + + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.sphere_update", text="Update",icon="SOLID") + + #col.label(text="Parameters:") + col.prop(obj.pov, "sphere_radius", text="Radius of Sphere") + + +class OBJECT_PT_povray_obj_cone(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Cone" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'CONE' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'CONE': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Cone base radius: " + str(obj.pov.cone_base_radius)) + col.label(text="Cone cap radius: " + str(obj.pov.cone_cap_radius)) + col.label(text="Cone proxy segments: " + str(obj.pov.cone_segments)) + col.label(text="Cone height: " + str(obj.pov.cone_height)) + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.cone_update", text="Update",icon="MESH_CONE") + + #col.label(text="Parameters:") + col.prop(obj.pov, "cone_base_radius", text="Radius of Cone Base") + col.prop(obj.pov, "cone_cap_radius", text="Radius of Cone Cap") + col.prop(obj.pov, "cone_segments", text="Segmentation of Cone proxy") + col.prop(obj.pov, "cone_height", text="Height of the cone") + +class OBJECT_PT_povray_obj_superellipsoid(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Superquadric ellipsoid" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'SUPERELLIPSOID' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'SUPERELLIPSOID': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Radial segmentation: " + str(obj.pov.se_u)) + col.label(text="Lateral segmentation: " + str(obj.pov.se_v)) + col.label(text="Ring shape: " + str(obj.pov.se_n1)) + col.label(text="Cross-section shape: " + str(obj.pov.se_n2)) + col.label(text="Fill up and down: " + str(obj.pov.se_edit)) + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.superellipsoid_update", text="Update",icon="MOD_SUBSURF") + + #col.label(text="Parameters:") + col.prop(obj.pov, "se_u") + col.prop(obj.pov, "se_v") + col.prop(obj.pov, "se_n1") + col.prop(obj.pov, "se_n2") + col.prop(obj.pov, "se_edit") + + +class OBJECT_PT_povray_obj_torus(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Torus" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'TORUS' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'TORUS': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Torus major radius: " + str(obj.pov.torus_major_radius)) + col.label(text="Torus minor radius: " + str(obj.pov.torus_minor_radius)) + col.label(text="Torus major segments: " + str(obj.pov.torus_major_segments)) + col.label(text="Torus minor segments: " + str(obj.pov.torus_minor_segments)) + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.torus_update", text="Update",icon="MESH_TORUS") + + #col.label(text="Parameters:") + col.prop(obj.pov, "torus_major_radius") + col.prop(obj.pov, "torus_minor_radius") + col.prop(obj.pov, "torus_major_segments") + col.prop(obj.pov, "torus_minor_segments") + +class OBJECT_PT_povray_obj_supertorus(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray SuperTorus" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'SUPERTORUS' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'SUPERTORUS': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="SuperTorus major radius: " + str(obj.pov.st_major_radius)) + col.label(text="SuperTorus minor radius: " + str(obj.pov.st_minor_radius)) + col.label(text="SuperTorus major segments: " + str(obj.pov.st_u)) + col.label(text="SuperTorus minor segments: " + str(obj.pov.st_v)) + + col.label(text="SuperTorus Ring Manipulator: " + str(obj.pov.st_ring)) + col.label(text="SuperTorus Cross Manipulator: " + str(obj.pov.st_cross)) + col.label(text="SuperTorus Internal And External radii: " + str(obj.pov.st_ie)) + + col.label(text="SuperTorus accuracy: " + str(ob.pov.st_accuracy)) + col.label(text="SuperTorus max gradient: " + str(ob.pov.st_max_gradient)) + + + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.supertorus_update", text="Update",icon="MESH_TORUS") + + #col.label(text="Parameters:") + col.prop(obj.pov, "st_major_radius") + col.prop(obj.pov, "st_minor_radius") + col.prop(obj.pov, "st_u") + col.prop(obj.pov, "st_v") + col.prop(obj.pov, "st_ring") + col.prop(obj.pov, "st_cross") + col.prop(obj.pov, "st_ie") + #col.prop(obj.pov, "st_edit") #? + col.prop(obj.pov, "st_accuracy") + col.prop(obj.pov, "st_max_gradient") + +class OBJECT_PT_povray_obj_parametric(PovDataButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray Parametric surface" + COMPAT_ENGINES = {'POVRAY_RENDER'} + #bl_options = {'HIDE_HEADER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + obj = context.object + return (obj and obj.pov.object_as == 'PARAMETRIC' and (engine in cls.COMPAT_ENGINES)) + def draw(self, context): + layout = self.layout + + obj = context.object + + col = layout.column() + + if obj.pov.object_as == 'PARAMETRIC': + if obj.pov.unlock_parameters == False: + col.prop(obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED') + col.label(text="Minimum U: " + str(obj.pov.u_min)) + col.label(text="Minimum V: " + str(obj.pov.v_min)) + col.label(text="Maximum U: " + str(obj.pov.u_max)) + col.label(text="Minimum V: " + str(obj.pov.v_min)) + col.label(text="X Function: " + str(obj.pov.x_eq)) + col.label(text="Y Function: " + str(obj.pov.y_eq)) + col.label(text="Z Function: " + str(obj.pov.x_eq)) + + else: + col.prop(obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED') + col.label(text="3D view proxy may get out of synch") + col.active = obj.pov.unlock_parameters + + + layout.operator("pov.parametric_update", text="Update",icon="SCRIPTPLUGINS") + + col.prop(obj.pov, "u_min", text="Minimum U") + col.prop(obj.pov, "v_min", text="Minimum V") + col.prop(obj.pov, "u_max", text="Maximum U") + col.prop(obj.pov, "v_max", text="Minimum V") + col.prop(obj.pov, "x_eq", text="X Function") + col.prop(obj.pov, "y_eq", text="Y Function") + col.prop(obj.pov, "z_eq", text="Z Function") + + class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, bpy.types.Panel): bl_label = "Custom POV Code" COMPAT_ENGINES = {'POVRAY_RENDER'} @@ -857,7 +1306,86 @@ class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, bpy.types.Panel): col.label(text="Replace properties with:") col.prop(obj.pov, "replacement_text", text="") +############################################################################### +# Add Povray Objects +############################################################################### + +class Povray_primitives_add_menu(bpy.types.Menu): + """Define the menu with presets""" + bl_idname = "Povray_primitives_add_menu" + bl_label = "Povray" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + return (engine == 'POVRAY_RENDER') + + def draw(self,context): + layout = self.layout + layout.operator_context = 'INVOKE_REGION_WIN' + layout.menu(BasicShapesMenu.bl_idname, text = "Primitives",icon="GROUP") + layout.menu(ImportMenu.bl_idname, text = "Import",icon="IMPORT") + +class BasicShapesMenu(bpy.types.Menu): + bl_idname = "Basic_shapes_calls" + bl_label = "Basic_shapes" + + def draw(self,context): + pov = bpy.types.Object.pov #context.object.pov ? + layout = self.layout + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("pov.addplane", text="Infinite Plane",icon = 'MESH_PLANE') + layout.operator("pov.addbox", text="Box",icon = 'MESH_CUBE') + layout.operator("pov.addsphere", text="Sphere",icon = 'SOLID') + layout.operator("pov.addcylinder", text="Cylinder",icon="MESH_CYLINDER") + layout.operator("pov.cone_add", text="Cone",icon="MESH_CONE") + layout.operator("pov.addtorus", text="Torus",icon = 'MESH_TORUS') + layout.separator() + layout.operator("pov.addparametric", text="Parametric",icon = 'SCRIPTPLUGINS') + layout.operator("pov.addrainbow", text="Rainbow",icon="COLOR") + layout.operator("pov.addlathe", text="Lathe",icon = 'MOD_SCREW') + layout.operator("pov.addprism", text="Prism",icon = 'MOD_SOLIDIFY') + layout.operator("pov.addsuperellipsoid", text="Superquadric Ellipsoid",icon = 'MOD_SUBSURF') + layout.operator("pov.addheightfield", text="Height Field",icon="RNDCURVE") + layout.operator("pov.addspheresweep", text="Sphere Sweep",icon = 'FORCE_CURVE') + layout.separator() + layout.operator("pov.addblobsphere", text="Blob Sphere",icon = 'META_DATA') + layout.separator() + layout.label("Isosurfaces") + layout.operator("pov.addisosurfacebox", text="Isosurface Box",icon="META_CUBE") + layout.operator("pov.addisosurfacesphere", text="Isosurface Sphere",icon="META_BALL") + layout.operator("pov.addsupertorus", text="Supertorus",icon="SURFACE_NTORUS") + layout.separator() + layout.label(text = "Macro based") + layout.operator("pov.addpolygontocircle", text="Polygon To Circle Blending",icon="RETOPO") + layout.operator("pov.addloft", text="Loft",icon="SURFACE_NSURFACE") + +class ImportMenu(bpy.types.Menu): + bl_idname = "Importer_calls" + bl_label = "Import" + + def draw(self,context): + pov = bpy.types.Object.pov #context.object.pov ? + layout = self.layout + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("import_scene.avogadro", text="Avogadro",icon="FORCE_LENNARDJONES") + +def menu_func_add(self, context): + engine = context.scene.render.engine + if engine == 'POVRAY_RENDER': + self.layout.menu("Povray_primitives_add_menu", icon="PLUGIN") + +def menu_func_import(self, context): + engine = context.scene.render.engine + if engine == 'POVRAY_RENDER': + self.layout.operator("import_scene.avogadro", text="POV-Ray Avogadro (.pov)",icon="FORCE_LENNARDJONES") + + +############################################################################### +# Camera Povray Settings +############################################################################### class CAMERA_PT_povray_cam_dof(CameraDataButtonsPanel, bpy.types.Panel): bl_label = "POV-Ray Depth Of Field" COMPAT_ENGINES = {'POVRAY_RENDER'} @@ -911,3 +1439,4 @@ class TEXT_PT_povray_custom_code(TextButtonsPanel, bpy.types.Panel): text = context.space_data.text if text: layout.prop(text.pov, "custom_code", text="Add as POV code") + |