Skip to content
Snippets Groups Projects
primitives.py 75.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •     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'}
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
    ########################################ISOSURFACES##################################
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV isosurface box using also just a Blender mesh cube.
    
        Flag its primitive type with a specific pov.object_as attribute and lock edit mode
        to keep proxy consistency by hiding edit geometry."""
    
    
        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()
    
            self.report({'INFO'}, "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 = 'PovIsosurfaceBox'
    
            return {'FINISHED'}
    
    class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV isosurface sphere by a Blender mesh icosphere.
    
        Flag its primitive type with a specific pov.object_as attribute and lock edit mode
        to keep proxy consistency by hiding edit geometry."""
    
    
        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)
    
            self.report({'INFO'}, "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 = 'PovIsosurfaceSphere'
    
            return {'FINISHED'}
    
    class POVRAY_OT_sphere_sweep_add(bpy.types.Operator):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV sphere_sweep using a Blender NURBS curve.
    
        Flag its primitive type with a specific ob.pov.curveshape attribute and
        leave access to edit mode to keep user editable handles."""
    
    
        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()
    
            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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV blob using a Blender meta ball.
    
        No need to flag its primitive type as meta are exported to blobs
        and leave access to edit mode to keep user editable thresholds."""
    
    
        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')
    
    
    class POVRAY_OT_rainbow_add(bpy.types.Operator):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV rainbow using a Blender spot light.
    
        Rainbows indeed propagate along a visibility cone.
        Flag its primitive type with a specific ob.pov.object_as attribute
        and leave access to edit mode to keep user editable handles.
        Add a constraint to orient it towards camera because POV Rainbows
        are view dependant and having it always initially visible is less
        confusing """
    
    
        bl_idname = "pov.addrainbow"
        bl_label = "Rainbow"
        bl_description = "Add Rainbow"
        bl_options = {'REGISTER', 'UNDO'}
    
            bpy.ops.object.light_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 # deprecated in 2.8
    
            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.view_layer.objects.active = ob
    
            ob.select_set(True)
    
            return {'FINISHED'}
    
    class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV height_field using a displaced grid.
    
        texture slot fix and displace modifier will be needed because noise
        displace operator was deprecated in 2.8"""
    
    
        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",
    
        hf_filename: StringProperty(maxlen = 1024)
    
        hf_gamma: FloatProperty(
    
                name="Gamma",
                description="Gamma",
                min=0.0001, max=20.0, default=1.0)
    
    
        hf_premultiplied: BoolProperty(
    
        hf_smooth: BoolProperty(
    
        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)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            hf_slot = mat.pov_texture_slots.add()
            hf_slot.texture = hf_tex.name
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            #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)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            bpy.ops.mesh.primitive_grid_add(x_subdivisions=w, y_subdivisions=h,size = 0.5)
    
            ob = context.object
            ob.name = ob.data.name = '%s'%im_name
            ob.data.materials.append(mat)
            bpy.ops.object.mode_set(mode="EDIT")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # bpy.ops.mesh.noise(factor=1) # TODO replace by a displace modifier as noise deprecated in 2.8
    
    
            #needs a loop to select by index?
    
            #bpy.ops.object.material_slot_remove()
            #material just left there for now
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            mat.pov_texture_slots.clear()
    
            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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV torus using just a Blender torus.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        But flag its primitive type with a specific pov.object_as attribute and lock edit mode
        to keep proxy consistency by hiding edit geometry."""
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            #keep object rotation and location for the add object operator
            obrot = ob.rotation_euler
            obloc = ob.location
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            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)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            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")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV torus using using pov_torus_define() function."""
    
    
        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",
    
        mis: IntProperty(name = "Minor Segments",
    
        mar: FloatProperty(name = "Major Radius",
    
        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({'INFO'}, "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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Update the POV torus.
    
        Delete its previous proxy geometry and rerun pov_torus_define() function
        with the new parameters"""
    
    
        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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV prism using using an extruded curve."""
    
    
        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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            scn.collection.objects.link(ob)
    
            context.view_layer.objects.active = ob
    
            ob.select_set(True)
    
            ob.pov.curveshape = "prism"
            ob.name = ob.data.name = "Prism"
            return {'FINISHED'}
    
    ##############################PARAMETRIC######################################
    
    def pov_parametric_define(context, op, ob):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV parametric surfaces by math surface from add mesh extra objects addon."""
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
            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")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the representation of POV parametric surfaces using pov_parametric_define() function."""
    
        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",
    
        v_min: FloatProperty(name = "V Min",
    
        u_max: FloatProperty(name = "U Max",
    
        v_max: FloatProperty(name = "V Max",
    
        x_eq: StringProperty(
    
        y_eq: StringProperty(
    
                        maxlen=1024, default = "sin(u)*sin(v/8)+cos(v/8)*1.5")
    
        z_eq: StringProperty(
    
        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
    
            self.report({'INFO'}, "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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Update the representation of POV parametric surfaces.
    
        Delete its previous proxy geometry and rerun pov_parametric_define() function
        with the new parameters"""
    
        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):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Add the proxy mesh for POV Polygon to circle lofting macro"""
    
    
        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",
    
        polytocircle_ngon: IntProperty(name = "NGon",
    
        polytocircle_ngonR: FloatProperty(name = "NGon Radius",
    
        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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            #layers = 20*[False]
            #layers[0] = True
            bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='NGON',enter_editmode=True)
    
            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')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            bpy.ops.mesh.primitive_circle_add(vertices=numCircleVerts, radius=circleR, fill_type='NGON',enter_editmode=True)
    
            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')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='TRIFAN',enter_editmode=True)
    
                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'}
    
    class ImportPOV(bpy.types.Operator, ImportHelper):
        """Load Povray files"""
        bl_idname = "import_scene.pov"
        bl_label = "POV-Ray files (.pov/.inc)"
    
        bl_options = {'PRESET', 'UNDO'}
        COMPAT_ENGINES = {'POVRAY_RENDER'}
    
    
        files: CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'})
        directory: StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'})
    
        filter_glob: StringProperty(
    
        import_at_cur: BoolProperty(name="Import at Cursor Location",
    
                                        description = "Ignore Object Matrix",
                                        default=False)
    
            from mathutils import Matrix
            verts = []
            faces = []
            materials = []
    
            blendMats = [] ##############
            povMats = [] ##############
    
            lenverts = None
            lenfaces = None
            suffix = -1
            name = 'Mesh2_%s'%suffix
            name_search = False
            verts_search = False
            faces_search = False
            plane_search = False
            box_search = False
            cylinder_search = False
            sphere_search = False
            cone_search = False
    
            tex_search = False ##################
    
            cache = []
            matrixes = {}
            writematrix = False
            index = None
            value = None
            #filepov = bpy.path.abspath(self.filepath) #was used for single files
    
            def mat_search(cache):
    
                r = g = b = 0.5
                f = t = 0
                color = None
    
                for item, value in enumerate(cache):
    
                    if value == 'texture':
                        pass
    
                    if value == 'pigment':
    
                        if cache[item+2] in {'rgb','srgb'}:
                            pass
    
                        elif cache[item+2] in {'rgbf','srgbf'}:
                            pass
    
                        elif cache[item+2] in {'rgbt','srgbt'}:
                            try:
                                r,g,b,t = float(cache[item+3]),float(cache[item+4]),float(cache[item+5]),float(cache[item+6])
                            except:
                                r = g = b = t = float(cache[item+2])
                            color = (r,g,b,t)
    
                        elif cache[item+2] in {'rgbft','srgbft'}:
                            pass
    
                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
    
                    if mat.alpha != 1:
                        mat.use_transparency=True
    
                    for i, value in enumerate(colors):
                        if color == value:
    
                            ob.data.materials.append(bpy.data.materials[matNames[i]])
            for file in self.files:
                print ("Importing file: "+ file.name)
                filepov = self.directory + file.name
                for line in open(filepov):
                    string = line.replace("{"," ")
                    string = string.replace("}"," ")
                    string = string.replace("<"," ")
                    string = string.replace(">"," ")
                    string = string.replace(","," ")
                    lw = string.split()
                    lenwords = len(lw)
                    if lw:
                        if lw[0] == "object":
                            writematrix = True
                        if writematrix:
                            if lw[0] not in {"object","matrix"}:
                                index = lw[0]
                            if lw[0] in {"matrix"}:
                                value = [float(lw[1]),float(lw[2]),float(lw[3]),\
                                            float(lw[4]),float(lw[5]),float(lw[6]),\
                                            float(lw[7]),float(lw[8]),float(lw[9]),\
                                            float(lw[10]),float(lw[11]),float(lw[12])]
                                matrixes[index]=value
                                writematrix = False
                for line in open(filepov):
                    S = line.replace("{"," { ")
                    S = S.replace("}"," } ")
                    S = S.replace(","," ")
                    S = S.replace("<","")
                    S = S.replace(">"," ")
                    S = S.replace("="," = ")
                    S = S.replace(";"," ; ")
                    S = S.split()
                    lenS= len(S)
                    for i,word in enumerate(S):
        ##################Primitives Import##################
                        if word == 'cone':
                            cone_search = True
                            name_search = False
                        if cone_search:
                            cache.append(word)
                            if cache[-1] == '}':
                                try:
                                    x0 = float(cache[2])
                                    y0 = float(cache[3])
                                    z0 = float(cache[4])
                                    r0 = float(cache[5])
                                    x1 = float(cache[6])
                                    y1 = float(cache[7])
                                    z1 = float(cache[8])
                                    r1 = float(cache[9])
                                    # Y is height in most pov files, not z
                                    bpy.ops.pov.cone_add(base=r0, cap=r1, height=(y1-y0))
                                    ob = context.object
                                    ob.location = (x0,y0,z0)
                                    #ob.scale = (r,r,r)
    
                                    mat_search(cache)
    
                                cone_search = False
    
                        if word == 'plane':
                            plane_search = True
                            name_search = False
                        if plane_search:
                            cache.append(word)
                            if cache[-1] == '}':
                                try:
                                    bpy.ops.pov.addplane()
                                    ob = context.object
    
                                    mat_search(cache)
    
                                plane_search = False
    
                        if word == 'box':
                            box_search = True
                            name_search = False
                        if box_search:
                            cache.append(word)
                            if cache[-1] == '}':
                                try:
                                    x0 = float(cache[2])
                                    y0 = float(cache[3])
                                    z0 = float(cache[4])
                                    x1 = float(cache[5])
                                    y1 = float(cache[6])
                                    z1 = float(cache[7])
                                    #imported_corner_1=(x0, y0, z0)
                                    #imported_corner_2 =(x1, y1, z1)
                                    center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
                                    bpy.ops.pov.addbox()
                                    ob = context.object
                                    ob.location = center
    
                                    mat_search(cache)
    
                                box_search = False
    
                        if word == 'cylinder':
                            cylinder_search = True
                            name_search = False
                        if cylinder_search:
                            cache.append(word)
                            if cache[-1] == '}':
                                try:
                                    x0 = float(cache[2])
                                    y0 = float(cache[3])
                                    z0 = float(cache[4])
                                    x1 = float(cache[5])
                                    y1 = float(cache[6])
                                    z1 = float(cache[7])
                                    imported_cyl_loc=(x0, y0, z0)
                                    imported_cyl_loc_cap =(x1, y1, z1)
    
                                    r = float(cache[8])
    
    
                                    vec = Vector(imported_cyl_loc_cap ) - Vector(imported_cyl_loc)
                                    depth = vec.length
                                    rot = Vector((0, 0, 1)).rotation_difference(vec)  # Rotation from Z axis.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                                    trans = rot @ Vector((0, 0, depth / 2)) # Such that origin is at center of the base of the cylinder.
    
                                    #center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
                                    scaleZ = sqrt((x1-x0)**2+(y1-y0)**2+(z1-z0)**2)/2
                                    bpy.ops.pov.addcylinder(R=r, imported_cyl_loc=imported_cyl_loc, imported_cyl_loc_cap=imported_cyl_loc_cap)
                                    ob = context.object
                                    ob.location = (x0, y0, z0)
                                    ob.rotation_euler = rot.to_euler()
    
                                    ob.scale = (1,1,scaleZ)
    
    
                                    #scale data rather than obj?
                                    # bpy.ops.object.mode_set(mode='EDIT')
                                    # bpy.ops.mesh.reveal()
                                    # bpy.ops.mesh.select_all(action='SELECT')
    
                                    # bpy.ops.transform.resize(value=(1,1,scaleZ), orient_type='LOCAL')
    
                                    # bpy.ops.object.mode_set(mode='OBJECT')
    
                                    mat_search(cache)
    
    
                                except (ValueError):
                                    pass
                                cache = []
                                cylinder_search = False
                        if word == 'sphere':
                            sphere_search = True
                            name_search = False
                        if sphere_search:
                            cache.append(word)
                            if cache[-1] == '}':
    
                                x = y = z = r = 0
    
                                try:
                                    x = float(cache[2])
                                    y = float(cache[3])
                                    z = float(cache[4])
                                    r = float(cache[5])
    
                                except:
                                    x = y = z = float(cache[2])
                                    r = float(cache[3])
                                bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
                                ob = context.object
                                ob.location = (x,y,z)
                                ob.scale = (r,r,r)
                                mat_search(cache)
    
                                sphere_search = False
    
    ##################End Primitives Import##################
    
                        if word == '#declare':
                            name_search = True
                        if name_search:
                            cache.append(word)
                            if word == 'mesh2':
                                name_search = False
                                if cache[-2] == '=':
                                    name = cache[-3]
                                else:
                                    suffix+=1
                                cache = []
                            if word in {'texture',';'}:
                                name_search = False
                                cache = []
                        if word == 'vertex_vectors':
    
                             verts_search = True
    
                            cache.append(word)
    
                            if word == '}':
                                verts_search = False
                                lenverts=cache[2]
                                cache.pop()
                                cache.pop(0)
                                cache.pop(0)
                                cache.pop(0)
                                for i in range(int(lenverts)):
                                    x=i*3
                                    y=(i*3)+1
                                    z=(i*3)+2
                                    verts.append((float(cache[x]),float(cache[y]),float(cache[z])))
    
                                cache = []
    
                        #if word == 'face_indices':
                             #faces_search = True
                        if word == 'texture_list': ########
                            tex_search = True #######
                        if tex_search: #########
                            if word not in {'texture_list','texture','{','}','face_indices'} and word.isdigit() == False: ##############
                                povMats.append(word) #################
    
                            tex_search = False ################
                            faces_search = True
    
                            cache.append(word)
    
                            if word == '}':
                                faces_search = False
                                lenfaces = cache[2]
                                cache.pop()
                                cache.pop(0)
                                cache.pop(0)
                                cache.pop(0)
                                lf = int(lenfaces)
                                var=int(len(cache)/lf)
                                for i in range(lf):
                                    if var == 3:
                                        v0=i*3
                                        v1=i*3+1
                                        v2=i*3+2
                                        faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
                                    if var == 4:
                                        v0=i*4
                                        v1=i*4+1
                                        v2=i*4+2
                                        m=i*4+3
                                        materials.append((int(cache[m])))
                                        faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
                                    if var == 6:
                                        v0=i*6
                                        v1=i*6+1
                                        v2=i*6+2
                                        m0=i*6+3
                                        m1=i*6+4
                                        m2=i*6+5
                                        materials.append((int(cache[m0]),int(cache[m1]),int(cache[m2])))
                                        faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
    
                                #mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False)
    
    Dalai Felinto's avatar
    Dalai Felinto committed
                                #ob = object_utils.object_data_add(context, mesh, operator=None)
    
    
                                me = bpy.data.meshes.new(name) ########
                                ob = bpy.data.objects.new(name, me) ##########
    
                                bpy.context.collection.objects.link(ob) #########
    
                                me.from_pydata(verts, [], faces) ############
    
                                for mat in bpy.data.materials: ##############
                                    blendMats.append(mat.name) #############
                                for mName in povMats: #####################
                                    if mName not in blendMats: ###########
                                        povMat = bpy.data.materials.new(mName) #################
    
                                        mat_search(cache)
    
                                    ob.data.materials.append(bpy.data.materials[mName]) ###################
                                if materials: ##################
                                    for i,val in enumerate(materials): ####################
                                        try: ###################
                                            ob.data.polygons[i].material_index = val ####################
                                        except TypeError: ###################
                                            ob.data.polygons[i].material_index = int(val[0]) ##################
    
                                blendMats = [] #########################
                                povMats = [] #########################
                                materials = [] #########################
    
                                cache = []
                                name_search = True
                                if name in matrixes and self.import_at_cur==False:
                                    global_matrix = Matrix.Rotation(pi / 2.0, 4, 'X')
                                    ob = bpy.context.object
                                    matrix=ob.matrix_world
                                    v=matrixes[name]
    
                                    matrix[0][0] = v[0]
                                    matrix[1][0] = v[1]
                                    matrix[2][0] = v[2]
                                    matrix[0][1] = v[3]
                                    matrix[1][1] = v[4]
                                    matrix[2][1] = v[5]
                                    matrix[0][2] = v[6]
                                    matrix[1][2] = v[7]
                                    matrix[2][2] = v[8]
                                    matrix[0][3] = v[9]
                                    matrix[1][3] = v[10]
                                    matrix[2][3] = v[11]
    
                                    matrix = global_matrix*ob.matrix_world
                                    ob.matrix_world = matrix
                                verts = []
                                faces = []
    
    
                        # if word == 'pigment':
                            # try:
                                # #all indices have been incremented once to fit a bad test file
                                # r,g,b,t = float(S[2]),float(S[3]),float(S[4]),float(S[5])
    
                                # color = (r,g,b,t)
    
    
                            # except (IndexError):
                                # #all indices have been incremented once to fit alternate test file
                                # r,g,b,t = float(S[3]),float(S[4]),float(S[5]),float(S[6])
    
                                # color = (r,g,b,t)