Beispiel #1
0
 def process(self):
     if not any(output.is_linked for output in self.outputs):
         return
     InVert, InEdge, InEdSel = self.inputs
     OutVert, OutEdg, OutFace, ONVert, ONEdg, ONFace, OOVert, OOEdg, OOFace = self.outputs
     vertices_s = InVert.sv_get()
     topo = InEdge.sv_get()
     if len(topo[0][0]) == 2:
         bmlist= [bmesh_from_pydata(v, e, [], normal_update=True) for v,e in zip(vertices_s,topo)]
     else:
         bmlist= [bmesh_from_pydata(v, [], e, normal_update=True) for v,e in zip(vertices_s,topo)]
     rev, ree, ref, riv, rie, rif, rsv, rse, rsf = [],[],[],[],[],[],[],[],[]
     if InEdSel.is_linked:
         if self.sel_mode == "index":
             useedges = [np.array(bm.edges[:])[idxs] for bm, idxs in zip(bmlist, InEdSel.sv_get())]
         elif self.sel_mode == "mask":
             useedges = [np.extract(mask, bm.edges[:]) for bm, mask in zip(bmlist, InEdSel.sv_get())]
     else:
         useedges = [bm.edges for bm in bmlist]
     for bm,ind in zip(bmlist,useedges):
         geom = subdivide_edges(bm, edges=ind,
                 smooth=self.smooth,
                 smooth_falloff=int(self.falloff_type),
                 fractal=self.fractal, along_normal=self.along_normal,
                 cuts=self.cuts, seed=self.seed,
                 quad_corner_type=int(self.corner_type),
                 use_grid_fill=self.grid_fill,
                 use_single_edge=self.single_edge,
                 use_only_quads=self.only_quads,
                 use_smooth_even=self.smooth_even)
         new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
         rev.append(new_verts)
         ree.append(new_edges)
         ref.append(new_faces)
         if self.show_new:
             geo1 = geom['geom_inner']
             riv.append([tuple(v.co) for v in geo1 if isinstance(v, bmesh.types.BMVert)])
             rie.append([[v.index for v in e.verts] for e in geo1 if isinstance(e, bmesh.types.BMEdge)])
             rif.append([[v.index for v in f.verts] for f in geo1 if isinstance(f, bmesh.types.BMFace)])
         if self.show_old:
             geo2 = geom['geom_split']
             rsv.append([tuple(v.co) for v in geo2 if isinstance(v, bmesh.types.BMVert)])
             rse.append([[v.index for v in e.verts] for e in geo2 if isinstance(e, bmesh.types.BMEdge)])
             rsf.append([[v.index for v in f.verts] for f in geo2 if isinstance(f, bmesh.types.BMFace)])
         bm.free()
     OutVert.sv_set(rev)
     OutEdg.sv_set(ree)
     OutFace.sv_set(ref)
     ONVert.sv_set(riv)
     ONEdg.sv_set(rie)
     ONFace.sv_set(rif)
     OOVert.sv_set(rsv)
     OOEdg.sv_set(rse)
     OOFace.sv_set(rsf)
Beispiel #2
0
    def process(self):

        if not (self.outputs['Vers'].is_linked and self.inputs['Vers'].is_linked):
            return

        vertices = Vector_generate(self.inputs['Vers'].sv_get())
        faces = self.inputs['Pols'].sv_get()
        offset = self.inputs['Offset'].sv_get()[0]
        nsides = self.inputs['N sides'].sv_get()[0][0]
        radius = self.inputs['Radius'].sv_get()[0]

        outv = []
        oute = []
        outo = []
        outn = []

        # for each object
        for verts_obj, faces_obj in zip(vertices, faces):
            fullList(offset, len(faces_obj))
            fullList(radius, len(faces_obj))
            verlen = set(range(len(verts_obj)))

            bm = bmesh_from_pydata(verts_obj, [], faces_obj, normal_update=True)
            result = self.Offset_pols(bm, offset, radius, nsides, verlen)
            outv.append(result[0])
            oute.append(result[1])
            outo.append(result[2])
            outn.append(result[3])

        self.outputs['Vers'].sv_set(outv)
        self.outputs['Edgs'].sv_set(oute)
        self.outputs['OutPols'].sv_set(outo)
        self.outputs['InPols'].sv_set(outn)
    def modal(self, context, event):
        context.area.tag_redraw()
        scn = context.scene

        if event.type in {'MIDDLEMOUSE'}:
            return {'RUNNING_MODAL'}

        if event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        if event.type in {'RET'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.object.modifier_apply(apply_as='DATA', modifier="sv_bool")
            context.active_object.show_wire = False
            context.active_object.show_all_edges = False
            bpy.ops.object.mode_set(mode='EDIT')
            return {'FINISHED'}

        scalar = scn.BGL_OFFSET_SCALAR
        VB, PB = generate_boolean_geom(self.verts, self.normal, scalar)

        bm = bmesh_from_pydata(VB, [], PB)
        n_obj = new_obj(bm, "ExtractObject", "Extract_mesh")
        n_obj.hide = True

        obj = bpy.context.active_object
        attache_boolean_modifier(obj, n_obj)

        return {'PASS_THROUGH'}
Beispiel #4
0
    def process(self):
        # достаём два слота - вершины и полики
        if 'Centers' in self.outputs and self.outputs['Centers'].links or self.outputs['Normals'].links:
            if 'Polygons' in self.inputs and 'Vertices' in self.inputs and self.inputs['Polygons'].links and self.inputs['Vertices'].links:

                #if type(self.inputs['Poligons'].links[0].from_socket) == StringsSocket:
                pols = SvGetSocketAnyType(self, self.inputs['Polygons'])

                #if type(self.inputs['Vertices'].links[0].from_socket) == VerticesSocket:
                vers = SvGetSocketAnyType(self, self.inputs['Vertices'])
                normalsFORout = []
                for i, obj in enumerate(vers):
                    """
                    mesh_temp = bpy.data.meshes.new('temp')
                    mesh_temp.from_pydata(obj, [], pols[i])
                    mesh_temp.update(calc_edges=True)
                    """
                    bm = bmesh_from_pydata(obj, [], pols[i])

                    bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
                    bm.verts.ensure_lookup_table()
                    verts = bm.verts
                    tempobj = []

                    for idx in range(len(verts)):
                        tempobj.append(verts[idx].normal[:])

                    normalsFORout.append(tempobj)

                    bm.free()
                    #bpy.data.meshes.remove(mesh_temp)
                #print (normalsFORout)

                if 'Normals' in self.outputs and self.outputs['Normals'].links:
                    SvSetSocketAnyType(self, 'Normals', normalsFORout)
Beispiel #5
0
    def process(self):

        if not (self.inputs[0].is_linked and self.inputs[2].is_linked):
            return
        if not any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons', 'NewPolys']):
            return

        out, result_bevel_faces = [], []

        meshes = match_long_repeat(self.get_socket_data())
        for vertices, edges, faces, bevel_edges, offset, segments, profile in zip(*meshes):
            bm = bmesh_from_pydata(vertices, edges, faces)
            b_edges = get_bevel_edges(bm, bevel_edges)

            geom = list(bm.verts) + list(b_edges) + list(bm.faces)
            bevel_faces = bmesh.ops.bevel(
                bm, geom=geom, offset=offset,
                offset_type=int(self.offsetType), segments=segments,
                profile=profile, vertex_only=self.vertexOnly, material=-1)['faces']

            new_bevel_faces = [[v.index for v in face.verts] for face in bevel_faces]
            out.append(pydata_from_bmesh(bm))
            bm.free()
            result_bevel_faces.append(new_bevel_faces)

        Vertices, Edges, Polygons, NewPolygons = self.outputs
        Vertices.sv_set([i[0] for i in out])
        Edges.sv_set([i[1] for i in out])
        Polygons.sv_set([i[2] for i in out])
        NewPolygons.sv_set(result_bevel_faces)
Beispiel #6
0
    def process(self):
        vers = self.inputs['Vertices'].sv_get()
        pols = self.inputs['Polygons'].sv_get()

        normalsFORout = []
        for i, obj in enumerate(vers):
            """
            mesh_temp = bpy.data.meshes.new('temp')
            mesh_temp.from_pydata(obj, [], pols[i])
            mesh_temp.update(calc_edges=True)
            """
            bm = bmesh_from_pydata(obj, [], pols[i])

            bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
            bm.verts.ensure_lookup_table()
            verts = bm.verts
            tempobj = []

            for idx in range(len(verts)):
                tempobj.append(verts[idx].normal[:])

            normalsFORout.append(tempobj)
            bm.free()

        if self.outputs['Normals'].is_linked:
            self.outputs['Normals'].sv_set(normalsFORout)
Beispiel #7
0
def line(p1=[(0,0,0)], p2=[(1,0,0)], nverts=2, mode='pydata'):
    '''
    line(p1=[(0,0,0)], p2=[(1,0,0)], nverts=2, mode='pydata')
    not finished..

    '''
    nv = nverts

    if mode in {'pydata', 'bm'}:
        verts = []
        edges = []

        num_verts = 0
        for v1, v2 in zip(p1, p2):
            if nv == 2:
                verts.extend([v1, v2])
            elif nv > 2:
                x_seg = (v2[0] - v1[0]) / (nv-1)
                y_seg = (v2[1] - v1[1]) / (nv-1)
                z_seg = (v2[2] - v1[2]) / (nv-1)
                verts.append(v1)
                verts.extend([[v1[0] + (x_seg * i), v1[1] + (y_seg * i), v1[2] + (z_seg * i)] for i in range(1, nv-1)])
                verts.append(v2)

            edges.extend([[i + num_verts, i + 1 + num_verts] for i in range(nv-1)])
            num_verts = len(verts)

        if mode == 'pydata':
            return verts, edges
        else:
            return bmesh_from_pydata(verts, edges, [])

    if mode == 'np':
        pass
Beispiel #8
0
def rect(dim_x=1.0, dim_y=1.62, radius=0.0, nverts=5, matrix=None, mode='pydata'):

    xdim = dim_x / 2
    ydim = dim_y / 2

    if mode in {'pydata', 'bm'}:
        verts = []

        if radius == 0.0 or nverts < 2:
            verts = [[-xdim, ydim, 0], [xdim, ydim, 0], [xdim, -ydim, 0], [-xdim, -ydim, 0]]

        elif radius > 0.0 and radius < min(abs(dim_x), abs(dim_y)) and nverts >= 2:
            theta = HALF_PI / (nverts-1)
            xdim = xdim - radius
            ydim = ydim - radius
            coords = [[xdim, ydim], [xdim, -ydim], [-xdim, -ydim], [-xdim, ydim]]
            for (x, y), corner in zip(coords, range(4)):
                for i in range(nverts):
                    rad = theta * i
                    verts.append(((math.sin(rad + (corner*HALF_PI)) * radius) + x, (math.cos(rad + (corner*HALF_PI)) * radius) + y, 0))

        num_verts = len(verts)
        edges = [[i, i+1] for i in range(num_verts-1)] + [[num_verts-1, 0]]
        faces = [i for i in range(num_verts)]

        if mode == 'pydata':
            return verts, edges, [faces]
        else:
            return bmesh_from_pydata(verts, edges, [faces])

    if mode == 'np':
        pass
def remove_doubles_from_edgenet(verts_in, edges_in, distance):
    bm = bmesh_from_pydata(verts_in, edges_in, [])
    bmesh.ops.remove_doubles(bm, verts=bm.verts[:], dist=distance)
    verts_out = [v.co.to_tuple() for v in bm.verts]
    edges_out = [[j.index for j in i.verts] for i in bm.edges]

    return verts_out, edges_out
Beispiel #10
0
def solidify(vertices, faces, t, verlen):

    if not faces or not vertices:
        return False

    if len(faces[0]) == 2:
        return False

    bm = bmesh_from_pydata(vertices, [], faces)
    geom_in = bm.verts[:]+bm.edges[:]+bm.faces[:]

    bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
    bmesh.ops.solidify(bm, geom=geom_in, thickness=t[0])

    edges = []
    faces = []
    newpols = []
    bm.verts.index_update()
    bm.edges.index_update()
    bm.faces.index_update()
    for edge in bm.edges[:]:
        edges.append([v.index for v in edge.verts[:]])
    verts = [vert.co[:] for vert in bm.verts[:]]
    for face in bm.faces:
        indexes = [v.index for v in face.verts[:]]
        faces.append(indexes)
        if not verlen.intersection(indexes):
            newpols.append(indexes)
    bm.clear()
    bm.free()
    return (verts, edges, faces, newpols)
Beispiel #11
0
def make_bmesh_geometry(node, context, geometry, idx, layers):
    scene = context.scene
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    verts, edges, matrix, _, _ = geometry
    name = node.basemesh_name + '.' + str("%04d" % idx)

    # remove object
    if name in objects:
        obj = objects[name]
        # assign the object an empty mesh, this allows the current mesh
        # to be uncoupled and removed from bpy.data.meshes
        obj.data = assign_empty_mesh(idx)

        # remove uncoupled mesh, and add it straight back.
        if name in meshes:
            meshes.remove(meshes[name])
        mesh = meshes.new(name)
        obj.data = mesh
    else:
        # this is only executed once, upon the first run.
        mesh = meshes.new(name)
        obj = objects.new(name, mesh)
        scene.objects.link(obj)

    # at this point the mesh is always fresh and empty
    obj['idx'] = idx
    obj['basename'] = node.basemesh_name

    data_layers = None
    if node.distance_doubles > 0.0:
        bm = bmesh_from_pydata(verts, edges, [])
        verts, edges, faces, d1, d2 = shrink_geometry(bm, node.distance_doubles, layers)
        data_layers = d1, d2

    force_pydata(obj.data, verts, edges)
    obj.update_tag(refresh={'OBJECT', 'DATA'})

    if node.live_updates:

        if 'sv_skin' in obj.modifiers:
            sk = obj.modifiers['sv_skin']
            obj.modifiers.remove(sk)

        if 'sv_subsurf' in obj.modifiers:
            sd = obj.modifiers['sv_subsurf']
            obj.modifiers.remove(sd)

        _ = obj.modifiers.new(type='SKIN', name='sv_skin')
        b = obj.modifiers.new(type='SUBSURF', name='sv_subsurf')
        b.levels = node.levels
        b.render_levels = node.render_levels

    if matrix:
        matrix = matrix_sanitizer(matrix)
        obj.matrix_local = matrix
    else:
        obj.matrix_local = Matrix.Identity(4)

    return obj, data_layers
Beispiel #12
0
    def storage_set_data(self, storage):
        geom = storage['geom']
        name = storage['params']["obj_name"]
        geom_dict = json.loads(geom)

        if not geom_dict:
            print(self.name, 'contains no flatten geom')
            return

        unrolled_geom = unflatten(geom_dict)
        verts = unrolled_geom['Vertices']
        edges = unrolled_geom['Edges']
        polygons = unrolled_geom['Polygons']
        matrix = unrolled_geom['Matrix']

        bm = bmesh_from_pydata(verts, edges, polygons)
        obj = generate_object(name, bm)
        obj.matrix_world = matrix

        # rename if obj existed
        if not obj.name == name:
            storage['params']["obj_name"] = obj.name
            self.id_data.freeze(hard=True)
            self.obj_name = obj.name
            self.id_data.unfreeze(hard=True)
def intersect_edges_3d(verts_in, edges_in, s_epsilon):

    bm = bmesh_from_pydata(verts_in, edges_in, [])

    edge_indices = [e.index for e in bm.edges]
    trim_indices = len(edge_indices)
    for edge in bm.edges:
        edge.select = True

    cm = CAD_ops(epsilon=s_epsilon)

    d = get_intersection_dictionary(cm, bm, edge_indices)
    unselect_nonintersecting(bm, d.keys(), edge_indices)

    # store non_intersecting edge sequencer
    add_back = [[i.index for i in edge.verts] for edge in bm.edges if not edge.select]

    update_mesh(bm, d)
    verts_out = [v.co.to_tuple() for v in bm.verts]
    edges_out = [[j.index for j in i.verts] for i in bm.edges]

    # optional correction, remove originals, add back those that are not intersecting.
    edges_out = edges_out[trim_indices:]
    edges_out.extend(add_back)
    bm.free()

    return verts_out, edges_out
Beispiel #14
0
    def process(self):

        # bmesh operations
        verts = self.inputs['verts'].sv_get()
        faces = self.inputs['faces'].sv_get()
        face_masks = self.inputs['face_masks'].sv_get()
        out_verts, out_faces = [], []

        for _verts, _faces, _face_mask in zip(verts, faces, face_masks):

            bm = bmesh_from_pydata(_verts, [], _faces, normal_update=True)

            sel = []
            add_sell = sel.append
            for f in (f for f in bm.faces if f.index in set(_face_mask)):
                f.select = True
                add_sell(f)

            generated_data = perform_mextrude(self, bm, sel)
            if generated_data:
                outv, outf = generated_data
                out_verts.append(outv)
                out_faces.append(outf)

        self.outputs['verts'].sv_set(out_verts)
        self.outputs['faces'].sv_set(out_faces)
def fillet(verts, edges, adj, num_seg):
    bm = bmesh_from_pydata(verts[0], edges[0], [])
    this_fillet = fillet_op0(bm, adj, num_seg)

    verts_out = [v.co[:] for v in bm.verts]
    edges_out = [[i.index for i in p.verts] for p in bm.edges[:]]
    return verts_out, edges_out
 def process(self):
     BML, Verts, Edges, Polys, vermask, edgmask, angllim = self.inputs
     o1,o2,o3,o4,o5 = self.outputs
     angle = angllim.sv_get()[0]
     ret = []
     bmlist = BML.sv_get([])
     if Verts.is_linked:
         bmlist.extend([bmesh_from_pydata(verts, edges, faces, normal_update=True) for verts, edges, faces in zip(*mlr([Verts.sv_get(), Edges.sv_get([[]]), Polys.sv_get([[]])]))])
     if vermask.is_linked:
         verm = [np.array(bm.verts[:])[ma] for bm,ma in zip(bmlist,vermask.sv_get())]
     else:
         verm = [bm.verts for bm in bmlist]
     if edgmask.is_linked:
         edgm = [np.array(bm.edges[:])[ma] for bm,ma in zip(bmlist,edgmask.sv_get())]
     else:
         edgm = [bm.edges for bm in bmlist]
     udb, dlm = self.use_dissolve_boundaries, self.delimit
     for bm, ang, vm, em in zip(bmlist, safc(bmlist, angle), verm, edgm):
         # it's a little undocumented..
         ret.append(dissolve_limit(bm, angle_limit=ang, use_dissolve_boundaries=udb, verts=vm, edges=em, delimit=dlm)['region'])
     if o1.is_linked:
         o1.sv_set([[v.co[:] for v in bm.verts]for bm in bmlist])
     if o2.is_linked:
         o2.sv_set([[[i.index for i in e.verts] for e in bm.edges]for bm in bmlist])
     if o3.is_linked:
         o3.sv_set([[[i.index for i in p.verts] for p in bm.faces]for bm in bmlist])
     if o4.is_linked:
         o4.sv_set(ret)
     if o5.is_linked:
         o5.sv_set(bmlist)
Beispiel #17
0
def grid(dim_x=1.0, dim_y=1.62, nx=2, ny=2, anchor=0, matrix=None, mode='pydata'):
    '''

    dim_x   -   total dimension on x side
    dim_y   -   total dimension on y side
    nx      -   num verts on x side
    ny      -   num verts on y side
    anchor  -   1 --- 2 --- 3
                -           -
                8     0     4
                -           -
                7 --- 6 --- 5
                default is centered (0)

    '''

    xside = dim_x / 2
    yside = dim_y / 2
    nx = max(2, nx)
    ny = max(2, ny)

    anchors = {
        1: (0,      dim_x, 0,      dim_y),
        2: (-xside, xside, 0,      dim_y),
        3: (-dim_x, 0,     0,      dim_y),
        4: (-dim_x, 0,     -yside, yside),
        5: (-dim_x, 0,     0,     -dim_y),
        6: (-xside, xside, 0,     -dim_y),
        7: (0,      dim_x, 0,     -dim_y),
        8: (0,      dim_x, -yside, yside),
        0: (-xside, xside, -yside, yside)
    }.get(anchor, (-xside, xside, -yside, yside))


    if mode in {'pydata', 'bm'}:
        verts = []
        faces = []
        add_face = faces.append
        total_range = ((ny-1) * (nx))

        a, b = anchors[:2]
        c, d = anchors[2:]
        x = np.linspace(a, b, nx)
        y = np.linspace(c, d, ny)
        f = np.vstack(np.meshgrid(x, y, 0)).reshape(3, -1).T
        verts = f.tolist()

        for i in range(total_range):
            if not ((i + 1) % nx == 0):  # +1 is the shift
                add_face([i, i+nx, i+nx+1, i+1])  # clockwise

        if mode == 'pydata':
            return verts, [], faces
        else:
            return bmesh_from_pydata(vert, [], faces)


    if mode == 'np':
        pass
Beispiel #18
0
def circle(radius=1.0, phase=0, nverts=20, matrix=None, mode='pydata'):
    '''
    parameters:
        radius: float
        phase:  where to start the unit circle
        nverts: number of verts of the circle
        matrix: transformation matrix [not implemented yet]
        mode:   'np' or 'pydata'

        :  'pydata'
        usage:
            Verts, Edges, Faces = circle(nverts=20, radius=1.6, mode='pydata')
        info:
            Each return type will be a nested list.
            Verts: will generate [[x0,y0,z0],[x1,y1,z1], ....[xN,yN,zN]]
            Edges: will generate [[a,b],[b,c], ....[n,a]]
            Faces: a single wrapped polygon around the bounds of the shape

        :  'np'
        usage:
            Verts, Edges, Faces = circle(nverts=20, radius=1.6, mode='np')

    outputs Verts, Edges, Faces

        info:
            Each return type will be a numpy array
            Verts: generates [n*4] - Array([[x0,y0,z0,w0],[x1,y1,z1,w1], ....[xN,yN,zN,wN]])
            Edges: will be a [n*2] - Array([[a,b],[b,c], ....[n,a]])
            Faces: a single wrapped polygon around the bounds of the shape

            to convert to pydata please consult the numpy manual.

    '''

    if mode in {'pydata', 'bm'}:

        verts = []
        theta = TAU / nverts
        for i in range(nverts):
            rad = i * theta
            verts.append((math.sin(rad + phase) * radius, math.cos(rad + phase) * radius, 0))

        edges = [[i, i+1] for i in range(nverts-1)] + [[nverts-1, 0]]
        faces = [i for i in range(nverts)]

        if mode == 'pydata':
            return verts, edges, [faces]
        else:
            return bmesh_from_pydata(verts, edges, [faces])

    if mode == 'np':

        t = np.linspace(0, np.pi * 2 * (nverts - 1 / nverts), nverts)
        circ = np.array([np.cos(t + phase) * radius, np.sin(t + phase) * radius, np.zeros(nverts), np.zeros(nverts)])
        verts = np.transpose(circ)
        edges = np.array([[i, i+1] for i in range(nverts-1)] + [[nverts-1, 0]])
        faces = np.array([[i for i in range(nverts)]])
        return verts, edges, faces
Beispiel #19
0
def quad(side=1.0, radius=0.0, nverts=5, matrix=None, mode='pydata'):
    '''
    parameters:
        side:   gives the length of side of the rect
        radius: gives the radius of the rounded corners.
                - If the passed radius is equal to side/2 then you'll get a circle
                - if the passed radius exceeds side/2, then you will get rect
        nverts: if nverts is equal or greater than 2 then you will get rounded courners
                if the above radius is smaller or equal to side/2.
        matrix: ---
        mode:   ---

    outputs Verts, Edges, Faces

        info:
            Each return type will be a nested list.
            Verts: will generate [[x0,y0,z0],[x1,y1,z1], ....[xN,yN,zN]]
            Edges: will generate [[a,b],[b,c], ....[n,a]]
            Faces: a single wrapped polygon around the bounds of the shape


    '''

    if mode in {'pydata', 'bm'}:
        dim = side / 2

        edges, faces = [], []

        if radius > 0.0 and radius < dim and nverts >= 2:
            verts = []
            theta = HALF_PI / (nverts-1)
            ext = dim - radius
            coords = [[ext, ext], [ext, -ext], [-ext, -ext], [-ext, ext]]
            for (x, y), corner in zip(coords, range(4)):
                for i in range(nverts):
                    rad = theta * i
                    verts.append(((math.sin(rad + (corner*HALF_PI)) * radius) + x, (math.cos(rad + (corner*HALF_PI)) * radius) + y, 0))

        elif radius > 0.0 and radius == dim and nverts >= 2:
            verts, edges, faces = circle(radius=dim, nverts=((nverts*4)-4))

        else:
            verts = [[-dim, dim, 0], [dim, dim, 0], [dim, -dim, 0], [-dim, -dim, 0]]
        # elif radius == 0.0 or (radius > 0.0 and radius > dim):

        num_verts = len(verts)
        if not edges:
            edges = [[i, i+1] for i in range(num_verts-1)] + [[num_verts-1, 0]]
            faces = [i for i in range(num_verts)]

        if mode == 'pydata':
            return verts, edges, [faces]
        else:
            return bmesh_from_pydata(verts, edges, [faces])

    if mode == 'np':
        pass
Beispiel #20
0
    def process(self):
        inputs = self.inputs
        outputs = self.outputs

        try:
            verts_in = inputs['Verts_in'].sv_get(deepcopy=False)[0]
            edges_in = inputs['Edges_in'].sv_get(deepcopy=False)[0]
            linked = outputs['Verts_out'].is_linked
        except (IndexError, KeyError) as e:
            return

        bm = bmesh_from_pydata(verts_in, edges_in, [])

        edge_indices = [e.index for e in bm.edges]
        trim_indices = len(edge_indices)
        for edge in bm.edges:
            edge.select = True

        cm = CAD_ops(epsilon=self.epsilon)

        d = get_intersection_dictionary(cm, bm, edge_indices)
        unselect_nonintersecting(bm, d.keys(), edge_indices)

        # store non_intersecting edge sequencer
        add_back = [[i.index for i in edge.verts] for edge in bm.edges if not edge.select]

        update_mesh(bm, d)
        verts_out = [v.co.to_tuple() for v in bm.verts]
        edges_out = [[j.index for j in i.verts] for i in bm.edges]

        # optional correction, remove originals, add back those that are not intersecting.
        edges_out = edges_out[trim_indices:]
        edges_out.extend(add_back)
        bm.free()

        # post processing step to remove doubles
        if self.rm_switch:
            bm = bmesh_from_pydata(verts_out, edges=edges_out)
            bmesh.ops.remove_doubles(bm, verts=bm.verts[:], dist=self.rm_doubles)
            verts_out = [v.co.to_tuple() for v in bm.verts]
            edges_out = [[j.index for j in i.verts] for i in bm.edges]

        outputs['Verts_out'].sv_set([verts_out])
        outputs['Edges_out'].sv_set([edges_out])
    def process(self):
        if not (self.inputs['Vertices'].is_linked and self.inputs['Polygons'].is_linked):
            return
        if not (any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons', 'NewEdges', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]])
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        mask_s = self.inputs['Mask'].sv_get(default=[[True]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_new_edges = []
        result_new_faces = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, mask_s])

        for vertices, edges, faces, mask in zip(*meshes):

            bm = bmesh_from_pydata(vertices, edges, faces)
            fullList(mask, len(faces))

            b_faces = []
            for m, face in zip(mask, bm.faces):
                if m:
                    b_faces.append(face)

            res = bmesh.ops.triangulate(
                bm, faces=b_faces,
                quad_method=int(self.quad_mode),
                ngon_method=int(self.ngon_mode))

            b_new_edges = [tuple(v.index for v in edge.verts) for edge in res['edges']]
            b_new_faces = [[v.index for v in face.verts] for face in res['faces']]

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_new_edges.append(b_new_edges)
            result_new_faces.append(b_new_faces)

        if self.outputs['Vertices'].is_linked:
            self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['NewEdges'].is_linked:
            self.outputs['NewEdges'].sv_set(result_new_edges)
        if self.outputs['NewPolys'].is_linked:
            self.outputs['NewPolys'].sv_set(result_new_faces)
Beispiel #22
0
def calc_mesh_normals(vertices, edges, faces):
    bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
    vertex_normals = []
    face_normals = []
    for vertex in bm.verts:
        vertex_normals.append(tuple(vertex.normal))
    for face in bm.faces:
        face_normals.append(tuple(face.normal))
    bm.free()
    return vertex_normals, face_normals
Beispiel #23
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked and self.inputs['Polygons'].is_linked):
            return
        if not (any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]])
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        offsets_s = self.inputs['Offset'].sv_get()[0]
        segments_s = self.inputs['Segments'].sv_get()[0]
        profiles_s = self.inputs['Profile'].sv_get()[0]
        bevel_edges_s = self.inputs['BevelEdges'].sv_get(default=[[]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_bevel_faces = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, bevel_edges_s, offsets_s, segments_s, profiles_s])

        for vertices, edges, faces, bevel_edges, offset, segments, profile in zip(*meshes):

            bm = bmesh_from_pydata(vertices, edges, faces)

            if bevel_edges:
                b_edges = []
                for edge in bevel_edges:
                    b_edge = [e for e in bm.edges if set([v.index for v in e.verts]) == set(edge)]
                    b_edges.append(b_edge[0])
            else:
                b_edges = bm.edges

            geom = list(bm.verts) + list(b_edges) + list(bm.faces)
            bevel_faces = bmesh.ops.bevel(bm, geom=geom, offset=offset,
                            offset_type=int(self.offsetType), segments=segments,
                            profile=profile, vertex_only=self.vertexOnly,
                            #clamp_overlap=self.clampOverlap,
                            material=-1)['faces']
            new_bevel_faces = [[v.index for v in face.verts] for face in bevel_faces]
            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_bevel_faces.append(new_bevel_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['NewPolys'].is_linked:
            self.outputs['NewPolys'].sv_set(result_bevel_faces)
Beispiel #24
0
    def makecube(self, size, divx, divy, divz):
        if 0 in (divx, divy, divz):
            return [], []

        b = size / 2.0

        verts = [
            [b, b, -b], [b, -b, -b], [-b, -b, -b],
            [-b, b, -b], [b, b, b], [b, -b, b],
            [-b, -b, b], [-b, b, b]
        ]

        faces = [[0, 1, 2, 3], [4, 7, 6, 5],
                 [0, 4, 5, 1], [1, 5, 6, 2],
                 [2, 6, 7, 3], [4, 0, 3, 7]]

        edges = [[0, 4], [4, 5], [5, 1], [1, 0],
                 [5, 6], [6, 2], [2, 1], [6, 7],
                 [7, 3], [3, 2], [7, 4], [0, 3]]

        if (divx, divy, divz) == (1, 1, 1):
            return verts, edges, faces

        bm = bmesh_from_pydata(verts, [], faces)
        dist = 0.0001
        section_dict = {0: divx, 1: divy, 2: divz}

        for axis in range(3):

            num_sections = section_dict[axis]
            if num_sections == 1:
                continue

            step = 1 / num_sections
            v1 = Vector(tuple((b if (i == axis) else 0) for i in [0, 1, 2]))
            v2 = Vector(tuple((-b if (i == axis) else 0) for i in [0, 1, 2]))

            for section in range(num_sections):
                mid_vec = v1.lerp(v2, section * step)
                plane_no = v2 - mid_vec
                plane_co = mid_vec
                visible_geom = bm.faces[:] + bm.verts[:] + bm.edges[:]

                bmesh.ops.bisect_plane(
                    bm, geom=visible_geom, dist=dist,
                    plane_co=plane_co, plane_no=plane_no,
                    use_snap_center=False,
                    clear_outer=False, clear_inner=False)

        indices = lambda i: [j.index for j in i.verts]

        verts = [list(v.co.to_tuple()) for v in bm.verts]
        faces = [indices(face) for face in bm.faces]
        edges = [indices(edge) for edge in bm.edges]
        return verts, edges, faces
def make_bmesh_geometry(node, idx, context, verts, *topology):
    scene = context.scene
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    edges, faces, matrix = topology
    name = node.basemesh_name + "_" + str(idx)

    if name in objects:
        sv_object = objects[name]
    else:
        temp_mesh = default_mesh(name)
        sv_object = objects.new(name, temp_mesh)
        scene.objects.link(sv_object)

    # book-keeping via ID-props!? even this is can be broken by renames
    sv_object['idx'] = idx
    sv_object['madeby'] = node.name
    sv_object['basename'] = node.basemesh_name

    mesh = sv_object.data
    current_count = len(mesh.vertices)
    propose_count = len(verts)
    difference = (propose_count - current_count)

    ''' With this mode you make a massive assumption about the
        constant state of geometry. Assumes the count of verts
        edges/faces stays the same, and only updates the locations

        node.fixed_verts is not suitable for initial object creation
        but if over time you find that the only change is going to be
        vertices, this mode can be switched to to increase efficiency
    '''
    if node.fixed_verts and difference == 0:
        f_v = list(itertools.chain.from_iterable(verts))
        mesh.vertices.foreach_set('co', f_v)
        mesh.update()
    else:

        ''' get bmesh, write bmesh to obj, free bmesh'''
        bm = bmesh_from_pydata(verts, edges, faces)
        bm.to_mesh(sv_object.data)
        bm.free()

        sv_object.hide_select = False

    if matrix:
        matrix = matrix_sanitizer(matrix)
        if node.extended_matrix:
            sv_object.data.transform(matrix)
            sv_object.matrix_local = Matrix.Identity(4)
        else:
            sv_object.matrix_local = matrix
    else:
        sv_object.matrix_local = Matrix.Identity(4)
Beispiel #26
0
    def process(self):
        vers = self.inputs['Vertices'].sv_get()
        pols = self.inputs['Polygons'].sv_get()

        normalsFORout = []
        for i, obj in enumerate(vers):
            bm = bmesh_from_pydata(obj, [], pols[i], normal_update=True)
            normalsFORout.append([v.normal[:] for v in bm.verts])
            bm.free()
        
        self.outputs['Normals'].sv_set(normalsFORout)
Beispiel #27
0
def make_bmesh_geometry_merged(node, idx, context, yielder_object):
    scene = context.scene
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    name = node.basemesh_name + "_" + str(idx)

    if name in objects:
        sv_object = objects[name]
    else:
        temp_mesh = default_mesh(name)
        sv_object = objects.new(name, temp_mesh)
        scene.objects.link(sv_object)

    # book-keeping via ID-props!
    sv_object['idx'] = idx
    sv_object['madeby'] = node.name
    sv_object['basename'] = node.basemesh_name

    vert_count = 0
    big_verts = []
    big_edges = []
    big_faces = []

    for result in yielder_object:

        verts, topology = result
        edges, faces, matrix = topology

        if matrix:
            matrix = matrix_sanitizer(matrix)
            verts = [matrix * Vector(v) for v in verts]

        big_verts.extend(verts)
        big_edges.extend([[a + vert_count, b + vert_count] for a, b in edges])
        big_faces.extend([[j + vert_count for j in f] for f in faces])

        vert_count += len(verts)


    if node.fixed_verts and len(sv_object.data.vertices) == len(big_verts):
        mesh = sv_object.data
        f_v = list(itertools.chain.from_iterable(big_verts))
        mesh.vertices.foreach_set('co', f_v)
        mesh.update()
    else:
        ''' get bmesh, write bmesh to obj, free bmesh'''
        bm = bmesh_from_pydata(big_verts, big_edges, big_faces, normal_update=node.calc_normals)
        bm.to_mesh(sv_object.data)
        bm.free()

    sv_object.hide_select = False
    sv_object.matrix_local = Matrix.Identity(4)
Beispiel #28
0
def fill_holes(vertices, edges, s):

    if not edges and not vertices:
        return False

    if len(edges[0]) != 2:
        return False
    
    bm = bmesh_from_pydata(vertices, edges, [])

    bmesh.ops.holes_fill(bm, edges=bm.edges[:], sides=s)
    verts, edges, faces = pydata_from_bmesh(bm)
    return (verts, edges, faces)
Beispiel #29
0
    def process(self):

        inputs = self.inputs
        outputs = self.outputs

        if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked):
            return

        named = ['Vertices', 'Edges', 'Polygons']
        if not (any(outputs[name].is_linked for name in named)):
            return

        vertices_s = inputs['Vertices'].sv_get(default=[[]])
        faces_s = inputs['Polygons'].sv_get(default=[[]])

        result_vertices = []
        result_edges = []
        result_faces = []

        meshes = match_long_repeat([vertices_s, faces_s])

        for vertices, faces in zip(*meshes):

            bm = bmesh_from_pydata(vertices, [], faces)

            new_edges = []
            new_faces = []

            for f in bm.faces:
                coords = [v.co for v in f.verts]
                indices = [v.index for v in f.verts]

                if len(coords) > 3:
                    for pol in tessellate([coords]):
                        new_faces.append([indices[i] for i in pol])
                else:
                    new_faces.append([v.index for v in f.verts])

            result_vertices.append([v.co[:] for v in bm.verts])
            result_edges.append(new_edges)
            result_faces.append(new_faces)

        output_list = [
            ['Vertices', result_vertices],
            ['Edges', result_edges],
            ['Polygons', result_faces]
        ]

        for output_name, output_data in output_list:
            if outputs[output_name].is_linked:
                outputs[output_name].sv_set(output_data)
Beispiel #30
0
def get_lathed_geometry(node, verts, edges, cent, axis, dvec, angle, steps):

    bm = bmesh_from_pydata(verts, edges, [])
    geom = bm.verts[:] + bm.edges[:]

    spin(bm, geom=geom, cent=cent, axis=axis, dvec=dvec, angle=angle, steps=steps, use_duplicate=0)

    if node.remove_doubles:
        bmesh.ops.remove_doubles(bm, verts=bm.verts[:], dist=node.dist)

    v = [v.co[:] for v in bm.verts]
    p = [[i.index for i in p.verts] for p in bm.faces[:]]
    bm.free()
    return v, p
Beispiel #31
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not (any(
                self.outputs[name].is_linked for name in
            ['Vertices', 'Edges', 'Polygons', 'NewEdges', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]],
                                                    deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        if 'FaceData' in self.inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]
        mask_s = self.inputs['Mask'].sv_get(default=[[True]], deepcopy=False)

        result_vertices = []
        result_edges = []
        result_faces = []
        result_face_data = []
        result_new_edges = []
        result_new_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, face_data_s, mask_s])

        for vertices, edges, faces, face_data, mask in zip(*meshes):
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   markup_face_data=True)
            mask_matched = repeat_last_for_length(mask, len(faces))

            b_faces = []
            for m, face in zip(mask_matched, bm.faces):
                if m:
                    b_faces.append(face)

            res = bmesh.ops.triangulate(bm,
                                        faces=b_faces,
                                        quad_method=self.quad_mode,
                                        ngon_method=self.ngon_mode)

            b_new_edges = [
                tuple(v.index for v in edge.verts) for edge in res['edges']
            ]
            b_new_faces = [[v.index for v in face.verts]
                           for face in res['faces']]

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_face_data.append(new_face_data)
            result_new_edges.append(b_new_edges)
            result_new_faces.append(b_new_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(result_face_data)
        self.outputs['NewEdges'].sv_set(result_new_edges)
        self.outputs['NewPolys'].sv_set(result_new_faces)
Beispiel #32
0
    def process(self):
        if not any(output.is_linked for output in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Faces'].sv_get(default=[[]])
        masks_s = self.inputs['VertMask'].sv_get(default=[[1]])
        iterations_s = self.inputs['Iterations'].sv_get()[0]
        if not self.laplacian:
            clip_dist_s = self.inputs['ClipDist'].sv_get()[0]
        else:
            clip_dist_s = [0.0]
        factor_s = self.inputs['Factor'].sv_get()[0]
        if self.laplacian:
            border_factor_s = self.inputs['BorderFactor'].sv_get()[0]
        else:
            border_factor_s = [0.0]

        result_vertices = []
        result_edges = []
        result_faces = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, clip_dist_s, factor_s,
            border_factor_s, iterations_s
        ])
        for vertices, edges, faces, masks, clip_dist, factor, border_factor, iterations in zip(
                *meshes):
            fullList(masks, len(vertices))

            bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
            bm.verts.ensure_lookup_table()
            bm.edges.ensure_lookup_table()
            bm.faces.ensure_lookup_table()
            selected_verts = [
                vert for mask, vert in zip(masks, bm.verts) if mask
            ]

            for i in range(iterations):
                if self.laplacian:
                    # for some reason smooth_laplacian_vert does not work properly if faces are not selected
                    for f in bm.faces:
                        f.select = True
                    bmesh.ops.smooth_laplacian_vert(
                        bm,
                        verts=selected_verts,
                        lambda_factor=factor,
                        lambda_border=border_factor,
                        use_x=self.use_x,
                        use_y=self.use_y,
                        use_z=self.use_z,
                        preserve_volume=self.preserve_volume)
                else:
                    bmesh.ops.smooth_vert(bm,
                                          verts=selected_verts,
                                          factor=factor,
                                          mirror_clip_x=self.mirror_clip_x,
                                          mirror_clip_y=self.mirror_clip_y,
                                          mirror_clip_z=self.mirror_clip_z,
                                          clip_dist=clip_dist,
                                          use_axis_x=self.use_x,
                                          use_axis_y=self.use_y,
                                          use_axis_z=self.use_z)

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Faces'].sv_set(result_faces)
def make_bmesh_geometry(node, context, geometry, idx, layers):
    scene = context.scene
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    verts, edges, matrix, _, _ = geometry
    name = node.basemesh_name + '.' + str("%04d" % idx)

    # remove object
    if name in objects:
        obj = objects[name]
        # assign the object an empty mesh, this allows the current mesh
        # to be uncoupled and removed from bpy.data.meshes
        obj.data = assign_empty_mesh(idx)

        # remove uncoupled mesh, and add it straight back.
        if name in meshes:
            meshes.remove(meshes[name])
        mesh = meshes.new(name)
        obj.data = mesh
    else:
        # this is only executed once, upon the first run.
        mesh = meshes.new(name)
        obj = objects.new(name, mesh)
        scene.objects.link(obj)

    # at this point the mesh is always fresh and empty
    obj['idx'] = idx
    obj['basename'] = node.basemesh_name

    data_layers = None
    if node.distance_doubles > 0.0:
        bm = bmesh_from_pydata(verts, edges, [])
        verts, edges, faces, d1, d2 = shrink_geometry(bm,
                                                      node.distance_doubles,
                                                      layers)
        data_layers = d1, d2

    force_pydata(obj.data, verts, edges)
    obj.update_tag(refresh={'OBJECT', 'DATA'})

    if node.live_updates:

        if 'sv_skin' in obj.modifiers:
            sk = obj.modifiers['sv_skin']
            obj.modifiers.remove(sk)

        if 'sv_subsurf' in obj.modifiers:
            sd = obj.modifiers['sv_subsurf']
            obj.modifiers.remove(sd)

        _ = obj.modifiers.new(type='SKIN', name='sv_skin')
        b = obj.modifiers.new(type='SUBSURF', name='sv_subsurf')
        b.levels = node.levels
        b.render_levels = node.render_levels

    if matrix:
        matrix = matrix_sanitizer(matrix)
        obj.matrix_local = matrix
    else:
        obj.matrix_local = Matrix.Identity(4)

    return obj, data_layers
Beispiel #34
0
def section(cut_me_vertices, cut_me_edges, mx, pp, pno, FILL=False, TRI=True):
    """Finds the section mesh between a mesh and a plane
    cut_me: Blender Mesh - the mesh to be cut
    mx: Matrix - The matrix of object of the mesh for correct coordinates
    pp: Vector - A point on the plane
    pno: Vector - The cutting plane's normal
    Returns: Mesh - the resulting mesh of the section if any or
             Boolean - False if no section exists"""

    def equation_plane(point, normal_dest):
        # получаем коэффициенты уравнения плоскости по точке и нормали
        normal = normal_dest.normalized()
        A = normal.x
        B = normal.y
        C = normal.z
        D = (A*point.x+B*point.y+C*point.z)*-1

        if A < 0.0:
            A *= -1
            B *= -1
            C *= -1
            D *= -1

        return (A, B, C, D)

    def point_on_plane(v1, ep):
        formula = ep[0]*v1.x+ep[1]*v1.y+ep[2]*v1.z+ep[3]
        if formula == 0.0:
            return True
        else:
            return False

    if not cut_me_edges or not cut_me_vertices:
        return False

    verts = []
    ed_xsect = {}
    x_me = {}

    ep = equation_plane(pp, pno)
    cut_me_polygons = []
    if len(cut_me_edges[0]) > 2:
        cut_me_polygons = cut_me_edges.copy()
        cut_me_edges = []

    new_me = bpy.data.meshes.new('tempus')
    new_me.from_pydata(cut_me_vertices, cut_me_edges, cut_me_polygons)
    new_me.update(calc_edges=True)

    for ed_idx, ed in enumerate(new_me.edges):
        # getting a vector from each edge vertices to a point on the plane
        # first apply transformation matrix so we get the real section

        vert1 = ed.vertices[0]
        v1 = new_me.vertices[vert1].co @ mx.transposed()

        vert2 = ed.vertices[1]
        v2 = new_me.vertices[vert2].co @ mx.transposed()

        vec = v2-v1
        mul = vec @ pno
        if mul == 0.0:
            if not point_on_plane(v1, ep):
                # parallel and not on plane
                continue

        epv = ep[0]*vec.x + ep[1]*vec.y + ep[2]*vec.z
        if epv == 0:
            t0 = 0
        else:
            t0 = -(ep[0]*v1.x+ep[1]*v1.y+ep[2]*v1.z + ep[3]) / epv

        pq = vec*t0+v1
        if (pq-v1).length <= vec.length and (pq-v2).length <= vec.length:
            verts.append(pq)
            ed_xsect[ed.key] = len(ed_xsect)

    edges = []
    for f in new_me.polygons:
        # get the edges that the intersecting points form
        # to explain this better:
        # If a face has an edge that is proven to be crossed then use the
        # mapping we created earlier to connect the edges properly
        ps = [ed_xsect[key] for key in f.edge_keys if key in ed_xsect]

        if len(ps) == 2:
            edges.append(tuple(ps))

    x_me['Verts'] = verts
    x_me['Edges'] = edges
    bpy.data.meshes.remove(new_me)

    if x_me:
        if edges and FILL:

            bm = bmesh_from_pydata(verts, edges, [])
            bmesh.ops.remove_doubles(bm, verts=bm.verts[:], dist=0.000002)
            fres = bmesh.ops.edgenet_prepare(bm, edges=bm.edges[:])

            if not TRI:
                # Alt + F
                bmesh.ops.triangle_fill(bm, use_beauty=True, use_dissolve=False, edges=fres['edges'])
            else:
                # can generate N-Gons
                bmesh.ops.edgeloop_fill(bm, edges=fres['edges'])

            # in case there are islands generated by the above operations, and said islands have varying
            # normals (up/down flipped due to lack of surrounding information), then we force all faces
            # to conform to the normal as obtained by the Matrix that generates this cut.
            normal_consistent(bm, pno)

            bm.verts.index_update()
            bm.edges.index_update()
            bm.faces.index_update()

            verts, edges, faces = pydata_from_bmesh(bm)
            x_me['Verts'] = verts
            x_me['Edges'] = faces # edges   --  this was outputting faces into edges when fill was ticked?

            bm.clear()
            bm.free()


        return x_me
    else:
        return False
Beispiel #35
0
    def process(self):

        if not (self.inputs[0].is_linked and
                (self.inputs[2].is_linked or self.inputs[1].is_linked)):
            return
        if not any(self.outputs[name].is_linked
                   for name in ['Vertices', 'Edges', 'Polygons', 'NewPolys']):
            return

        verts_out = []
        edges_out = []
        faces_out = []
        face_data_out = []
        result_bevel_faces = []

        meshes = match_long_repeat(self.get_socket_data())

        for vertices, edges, faces, face_data, mask, offset, segments, profile, bevel_face_data, spread in zip(
                *meshes):
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))
            if bevel_face_data and isinstance(bevel_face_data, (list, tuple)):
                bevel_face_data = bevel_face_data[0]
            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   markup_face_data=True,
                                   normal_update=True)
            geom = self.create_geom(bm, mask)

            try:
                # we try the most likely blender binary compatible version first (official builds)

                bevel_faces = bmesh.ops.bevel(
                    bm,
                    geom=geom,
                    offset=offset,
                    offset_type=self.offsetType,
                    segments=segments,
                    profile=profile,
                    vertex_only=self.vertexOnly,
                    clamp_overlap=self.clamp_overlap,
                    loop_slide=self.loop_slide,
                    spread=spread,
                    miter_inner=self.miter_inner,
                    miter_outer=self.miter_outer,
                    # strength= (float)
                    # hnmode= (enum in ['NONE', 'FACE', 'ADJACENT', 'FIXED_NORMAL_SHADING'], default 'NONE')
                    material=-1)['faces']
            except TypeError as e:

                # if the "try" failed, we try the new form of bmesh.ops.bevel arguments..
                affect_geom = 'VERTICES' if self.vertexOnly else 'EDGES'

                bevel_faces = bmesh.ops.bevel(
                    bm,
                    geom=geom,
                    offset=offset,
                    offset_type=self.offsetType,
                    segments=segments,
                    profile=profile,
                    #   profile_type=  (enum:  'SUPERELLIPSE', 'CUSTOM' ), default super
                    affect=affect_geom,
                    clamp_overlap=self.clamp_overlap,
                    loop_slide=self.loop_slide,
                    spread=spread,
                    miter_inner=self.miter_inner,
                    miter_outer=self.miter_outer,
                    material=-1)['faces']

            except Exception as e:
                self.exception(e)

            new_bevel_faces = [[v.index for v in face.verts]
                               for face in bevel_faces]
            if not face_data:
                verts, edges, faces = pydata_from_bmesh(bm)
                verts_out.append(verts)
                edges_out.append(edges)
                faces_out.append(faces)
                if bevel_face_data != []:
                    new_face_data = []
                    for face in faces:
                        if set(face) in map(set, new_bevel_faces):
                            new_face_data.append(bevel_face_data)
                        else:
                            new_face_data.append(None)
                    face_data_out.append(new_face_data)
                else:
                    face_data_out.append([])
            else:
                verts, edges, faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
                verts_out.append(verts)
                edges_out.append(edges)
                faces_out.append(faces)
                if bevel_face_data != []:
                    new_face_data_m = []
                    for data, face in zip(new_face_data, faces):
                        if set(face) in map(set, new_bevel_faces):
                            new_face_data_m.append(bevel_face_data)
                        else:
                            new_face_data_m.append(data)
                    face_data_out.append(new_face_data_m)
                else:
                    face_data_out.append(new_face_data)
            bm.free()
            result_bevel_faces.append(new_bevel_faces)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Polygons'].sv_set(faces_out)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(face_data_out)
        self.outputs['NewPolys'].sv_set(result_bevel_faces)
def make_hull(vertices, params):
    if not vertices:
        return False

    verts, faces = [], [[]]

    # invoke the right convex hull function
    if params.hull_mode == '3D':
        bm = bmesh_from_pydata(vertices, [], [])
        res = bmesh.ops.convex_hull(bm,
                                    input=bm.verts[:],
                                    use_existing_faces=False)
        unused_v_indices = [v.index for v in res["geom_unused"]]

        if params.inside and params.outside:
            verts, _, faces = pydata_from_bmesh(bm)

        elif not params.inside and params.outside:
            bmesh.ops.delete(bm,
                             geom=[bm.verts[i] for i in unused_v_indices],
                             context='VERTS')
            verts, _, faces = pydata_from_bmesh(bm)

        elif not params.outside and params.inside:
            used_v_indices = set(range(len(vertices))) - set(unused_v_indices)
            bmesh.ops.delete(bm,
                             geom=[bm.verts[i] for i in used_v_indices],
                             context='VERTS')
            verts = [
                v[:] for idx, v in enumerate(vertices)
                if idx in unused_v_indices
            ]

    elif params.hull_mode == '2D':
        vertices_2d = get2d(params.plane, vertices)
        used_v_indices = mathutils.geometry.convex_hull_2d(vertices_2d)
        unused_v_indices = set(range(len(vertices))) - set(used_v_indices)

        bm = bmesh_from_pydata(vertices, [], [used_v_indices])

        if params.inside and params.outside:
            verts, _, faces = pydata_from_bmesh(bm)

        elif not params.inside and params.outside:
            bmesh.ops.delete(bm,
                             geom=[bm.verts[i] for i in unused_v_indices],
                             context='VERTS')
            if params.sort_edges:
                bm.faces.ensure_lookup_table()
                addv = verts.append
                _ = [addv(v.co[:]) for v in bm.faces[0].verts[:]]
                faces = [list(range(len(verts)))]
            else:
                verts, _, faces = pydata_from_bmesh(bm)

        elif not params.outside and params.inside:
            bmesh.ops.delete(bm,
                             geom=[bm.verts[i] for i in used_v_indices],
                             context='VERTS')
            verts, _, _ = pydata_from_bmesh(bm)

    bm.clear()
    bm.free()
    return (verts, faces)
Beispiel #37
0
    def process(self):
        inputs, outputs = self.inputs, self.outputs

        if self.dont_process():
            return

        result_vertices, result_edges, result_faces, result_face_data = [], [], [], []
        r_inner_vertices, r_inner_edges, r_inner_faces = [], [], []
        r_split_vertices, r_split_edges, r_split_faces = [], [], []

        use_mask = inputs['EdgeMask'].is_linked
        show_new = self.show_new and any(s.is_linked for s in outputs[4:7])
        show_old = self.show_old and any(s.is_linked for s in outputs[7:])
        use_face_data = inputs['FaceData'].is_linked and outputs[
            'FaceData'].is_linked
        output_numpy = any(self.out_np)

        meshes = self.get_data()

        for vertices, edges, faces, face_data, masks, cuts, smooth, fractal, along_normal, seed in zip(
                *meshes):
            if cuts < 1:
                result_vertices.append(vertices)
                result_edges.append(edges)
                result_faces.append(faces)
                result_face_data.append(face_data)
                r_inner_vertices.append(vertices)
                r_inner_edges.append(edges)
                r_inner_faces.append(faces)
                r_split_vertices.append(vertices)
                r_split_edges.append(edges)
                r_split_faces.append(faces)
                continue

            if use_face_data and len(face_data) > 0:
                if isinstance(face_data, ndarray):
                    face_data = numpy_full_list(face_data, len(faces)).tolist()
                else:
                    fullList(face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   markup_face_data=use_face_data,
                                   markup_edge_data=use_mask,
                                   normal_update=True)

            selected_edges = get_selected_edges(use_mask, masks, bm.edges)

            geom = subdivide_edges(bm,
                                   edges=selected_edges,
                                   smooth=smooth,
                                   smooth_falloff=self.falloff_type,
                                   fractal=fractal,
                                   along_normal=along_normal,
                                   cuts=cuts,
                                   seed=seed,
                                   quad_corner_type=self.corner_type,
                                   use_grid_fill=self.grid_fill,
                                   use_single_edge=self.single_edge,
                                   use_only_quads=self.only_quads,
                                   use_smooth_even=self.smooth_even)

            if output_numpy:
                new_verts, new_edges, new_faces, new_face_data = numpy_data_from_bmesh(
                    bm, self.out_np, face_data)
            else:
                if use_face_data and len(face_data) > 0:
                    new_verts, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                        bm, face_data)
                else:
                    new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
                    new_face_data = []

            result_vertices.append(new_verts)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_face_data.append(new_face_data)

            if show_new:
                inner_verts, inner_edges, inner_faces = get_partial_result_pydata(
                    geom['geom_inner'])
                r_inner_vertices.append(inner_verts)
                r_inner_edges.append(inner_edges)
                r_inner_faces.append(inner_faces)

            if show_old:
                split_verts, split_edges, split_faces = get_partial_result_pydata(
                    geom['geom_split'])
                r_split_vertices.append(split_verts)
                r_split_edges.append(split_edges)
                r_split_faces.append(split_faces)

            bm.free()

        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Faces'].sv_set(result_faces)
        outputs['FaceData'].sv_set(result_face_data)

        outputs['NewVertices'].sv_set(r_inner_vertices)
        outputs['NewEdges'].sv_set(r_inner_edges)
        outputs['NewFaces'].sv_set(r_inner_faces)

        outputs['OldVertices'].sv_set(r_split_vertices)
        outputs['OldEdges'].sv_set(r_split_edges)
        outputs['OldFaces'].sv_set(r_split_faces)
Beispiel #38
0
 def process(self):
     outputs = self.outputs
     if not outputs['Vertices'].is_linked:
         return
     IVerts, IFaces, IMask, Imatr = self.inputs
     vertices_s = IVerts.sv_get()
     faces_s = IFaces.sv_get()
     linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
     linked_other_polygons = outputs['OtherPolys'].is_linked
     result_vertices = []
     result_edges = []
     result_faces = []
     result_extruded_faces = []
     result_other_faces = []
     bmlist = [
         bmesh_from_pydata(verts, [], faces)
         for verts, faces in zip(vertices_s, faces_s)
     ]
     trans = Imatr.sv_get()
     if IMask.is_linked:
         flist = [
             np.extract(mask, bm.faces[:])
             for bm, mask in zip(bmlist, IMask.sv_get())
         ]
     else:
         flist = [bm.faces for bm in bmlist]
     for bm, selfaces in zip(bmlist, flist):
         extrfaces = extrude_discrete_faces(bm, faces=selfaces)['faces']
         fullList(trans, len(extrfaces))
         new_extruded_faces = []
         for face, ma in zip(extrfaces, trans):
             normal = face.normal
             if normal[0] == 0 and normal[1] == 0:
                 m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(
                     pi, 4, 'X')
             else:
                 z_axis = normal
                 x_axis = Vector(
                     (z_axis[1] * -1, z_axis[0], 0)).normalized()
                 y_axis = z_axis.cross(x_axis).normalized()
                 m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])
                                    ])).to_4x4()
             m = (Matrix.Translation(face.calc_center_median())
                  @ m_r).inverted()
             transform(bm, matrix=ma, space=m, verts=face.verts)
             if linked_extruded_polygons or linked_other_polygons:
                 new_extruded_faces.append([v.index for v in face.verts])
         new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
         bm.free()
         new_other_faces = [
             f for f in new_faces if f not in new_extruded_faces
         ] if linked_other_polygons else []
         result_vertices.append(new_vertices)
         result_edges.append(new_edges)
         result_faces.append(new_faces)
         result_extruded_faces.append(new_extruded_faces)
         result_other_faces.append(new_other_faces)
     outputs['Vertices'].sv_set(result_vertices)
     outputs['Edges'].sv_set(result_edges)
     outputs['Polygons'].sv_set(result_faces)
     outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
     outputs['OtherPolys'].sv_set(result_other_faces)
Beispiel #39
0
def make_bmesh_geometry(node, obj_index, context, verts, *topology):
    collection = context.scene.collection
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    islands = None

    edges, faces, materials, matrix = topology
    name = f'{node.basedata_name}.{obj_index:04d}'

    if name in objects:
        sv_object = objects[name]
    else:
        temp_mesh = default_mesh(name)
        sv_object = objects.new(name, temp_mesh)
        collection.objects.link(sv_object)

    # book-keeping via ID-props!? even this is can be broken by renames
    sv_object['idx'] = obj_index
    sv_object['madeby'] = node.name
    sv_object['basedata_name'] = node.basedata_name

    mesh = sv_object.data
    current_count = len(mesh.vertices)
    propose_count = len(verts)
    difference = (propose_count - current_count)
    ''' With this mode you make a massive assumption about the
        constant state of geometry. Assumes the count of verts
        edges/faces stays the same, and only updates the locations

        node.fixed_verts is not suitable for initial object creation
        but if over time you find that the only change is going to be
        vertices, this mode can be switched to to increase efficiency
    '''
    if node.fixed_verts and difference == 0:
        f_v = list(itertools.chain.from_iterable(verts))
        mesh.vertices.foreach_set('co', f_v)
        mesh.update()
    else:
        ''' get bmesh, write bmesh to obj, free bmesh'''
        bm = bmesh_from_pydata(verts,
                               edges,
                               faces,
                               normal_update=node.calc_normals)
        if materials:
            for face, material in zip(bm.faces[:], materials):
                if material is not None:
                    face.material_index = material
        bm.to_mesh(sv_object.data)
        if node.randomize_vcol_islands:
            islands = find_islands_treemap(bm)
        bm.free()

        sv_object.hide_select = False

    if node.randomize_vcol_islands:
        set_vertices(sv_object, islands)

    if matrix:
        # matrix = matrix_sanitizer(matrix)
        if node.extended_matrix:
            sv_object.data.transform(matrix)
            sv_object.matrix_local = Matrix.Identity(4)
        else:
            sv_object.matrix_local = matrix
    else:
        sv_object.matrix_local = Matrix.Identity(4)
Beispiel #40
0
def voronoi3d_layer(n_src_sites, all_sites, make_regions, do_clip, clipping, skip_added=True):
    diagram = Voronoi(all_sites)
    src_sites = all_sites[:n_src_sites]

    region_verts = dict()
    region_verts_map = dict()
    n_sites = n_src_sites if skip_added else len(all_sites)
    for site_idx in range(n_sites):
        region_idx = diagram.point_region[site_idx]
        region = diagram.regions[region_idx]
        vertices = [tuple(diagram.vertices[i,:]) for i in region]
        region_verts[site_idx] = vertices
        region_verts_map[site_idx] = {vert_idx: i for i, vert_idx in enumerate(region)}

    open_sites = set()
    region_faces = defaultdict(list)
    for ridge_idx, sites in enumerate(diagram.ridge_points):
        site_from, site_to = sites
        ridge = diagram.ridge_vertices[ridge_idx]
        if -1 in ridge:
            open_sites.add(site_from)
            open_sites.add(site_to)

        site_from_ok = not skip_added or site_from < n_src_sites
        site_to_ok = not skip_added or site_to < n_src_sites

        if make_regions:
            if site_from_ok:
                face_from = [region_verts_map[site_from][i] for i in ridge]
                region_faces[site_from].append(face_from)

            if site_to_ok:
                face_to = [region_verts_map[site_to][i] for i in ridge]
                region_faces[site_to].append(face_to)
        else:
            if site_from_ok and site_to_ok:
                face_from = [region_verts_map[site_from][i] for i in ridge]
                region_faces[site_from].append(face_from)
                face_to = [region_verts_map[site_to][i] for i in ridge]
                region_faces[site_to].append(face_to)

    verts = [region_verts[i] for i in range(n_sites) if i not in open_sites]
    faces = [region_faces[i] for i in range(n_sites) if i not in open_sites]

    empty_faces = [len(f) == 0 for f in faces]
    verts = [vs for vs, mask in zip(verts, empty_faces) if not mask]
    faces = [fs for fs, mask in zip(faces, empty_faces) if not mask]
    edges = polygons_to_edges(faces, True)

    if not make_regions:
        verts_n, edges_n, faces_n = [], [], []
        for verts_i, edges_i, faces_i in zip(verts, edges, faces):
            used_verts = set(sum(faces_i, []))
            mask = [i in used_verts for i in range(len(verts_i))]
            verts_i, edges_i, faces_i = mask_vertices(verts_i, edges_i, faces_i, mask)
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        verts, edges, faces = verts_n, edges_n, faces_n

    if do_clip:
        verts_n, edges_n, faces_n = [], [], []
        bounds = calc_bounds(src_sites, clipping)
        for verts_i, edges_i, faces_i in zip(verts, edges, faces):
            bm = bmesh_from_pydata(verts_i, edges_i, faces_i)
            bmesh_clip(bm, bounds, fill=True)
            verts_i, edges_i, faces_i = pydata_from_bmesh(bm)
            bm.free()
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        verts, edges, faces = verts_n, edges_n, faces_n

    return verts, edges, faces
Beispiel #41
0
def voronoi3d_regions(sites, closed_only=True, recalc_normals=True, do_clip=False, clipping=1.0):
    diagram = Voronoi(sites)
    faces_per_site = defaultdict(list)
    nsites = len(diagram.point_region)
    nridges = len(diagram.ridge_points)
    open_sites = set()
    for ridge_idx in range(nridges):
        site_idx_1, site_idx_2 = diagram.ridge_points[ridge_idx]
        face = diagram.ridge_vertices[ridge_idx]
        if -1 in face:
            open_sites.add(site_idx_1)
            open_sites.add(site_idx_2)
            continue
        faces_per_site[site_idx_1].append(face)
        faces_per_site[site_idx_2].append(face)

    new_verts = []
    new_edges = []
    new_faces = []

    for site_idx in sorted(faces_per_site.keys()):
        if closed_only and site_idx in open_sites:
            continue
        done_verts = dict()
        bm = bmesh.new()
        add_vert = bm.verts.new
        add_face = bm.faces.new
        for face in faces_per_site[site_idx]:
            face_bm_verts = []
            for vertex_idx in face:
                if vertex_idx not in done_verts:
                    bm_vert = add_vert(diagram.vertices[vertex_idx])
                    done_verts[vertex_idx] = bm_vert
                else:
                    bm_vert = done_verts[vertex_idx]
                face_bm_verts.append(bm_vert)
            add_face(face_bm_verts)
        bm.verts.index_update()
        bm.verts.ensure_lookup_table()
        bm.faces.index_update()
        bm.edges.index_update()

        if closed_only and any (v.is_boundary for v in bm.verts):
            bm.free()
            continue

        if recalc_normals:
            bm.normal_update()
            bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])

        region_verts, region_edges, region_faces = pydata_from_bmesh(bm)
        bm.free()
        new_verts.append(region_verts)
        new_edges.append(region_edges)
        new_faces.append(region_faces)

    if do_clip:
        verts_n, edges_n, faces_n = [], [], []
        bounds = calc_bounds(sites, clipping)
        for verts_i, edges_i, faces_i in zip(new_verts, new_edges, new_faces):
            bm = bmesh_from_pydata(verts_i, edges_i, faces_i)
            bmesh_clip(bm, bounds, fill=True)
            bm.normal_update()
            bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
            verts_i, edges_i, faces_i = pydata_from_bmesh(bm)
            bm.free()
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        new_verts, new_edges, new_faces = verts_n, edges_n, faces_n

    return new_verts, new_edges, new_faces
Beispiel #42
0
    def process(self):
        # inputs
        if not self.inputs['Vertices'].is_linked:
            return

        vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        masks_s = self.inputs['Mask'].sv_get(default=[[1]], deepcopy=False)
        if self.transform_mode == "Matrix":
            matrices_s = [
                self.inputs['Matrices'].sv_get(default=[Matrix()],
                                               deepcopy=False)
            ]
            heights_s = [0.0]
            scales_s = [1.0]
        else:
            matrices_s = [[]]
            heights_s = self.inputs['Height'].sv_get(deepcopy=False)
            scales_s = self.inputs['Scale'].sv_get(deepcopy=False)
        if 'FaceData' in self.inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]

        need_mask_out = 'Mask' in self.outputs and self.outputs[
            'Mask'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_ext_vertices = []
        result_ext_edges = []
        result_ext_faces = []
        result_face_data = []
        result_mask = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s,
            scales_s, face_data_s
        ])

        for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration, face_data in zip(
                *meshes):
            if self.transform_mode == "Matrix":
                if not matrix_per_iteration:
                    matrix_per_iteration = [Matrix()]

            if self.multiple:
                if self.transform_mode == "Matrix":
                    n_iterations = len(matrix_per_iteration)
                else:
                    n_iterations = max(len(height_per_iteration),
                                       len(scale_per_iteration))
                    height_per_iteration_matched = repeat_last_for_length(
                        height_per_iteration, n_iterations)
                    scale_per_iteration_matched = repeat_last_for_length(
                        scale_per_iteration, n_iterations)
            else:
                n_iterations = 1
                matrix_per_iteration = [matrix_per_iteration]

            mask_matched = repeat_last_for_length(masks, len(faces))
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   normal_update=True,
                                   markup_face_data=True)
            mask_layer = bm.faces.layers.int.new('mask')
            bm.faces.ensure_lookup_table()
            #fill_faces_layer(bm, masks, 'mask', int, MASK, invert_mask=True)

            b_faces = []
            b_edges = set()
            b_verts = set()
            for mask, face in zip(mask_matched, bm.faces):
                if mask:
                    b_faces.append(face)
                    for edge in face.edges:
                        b_edges.add(edge)
                    for vert in face.verts:
                        b_verts.add(vert)

            extrude_geom = b_faces + list(b_edges) + list(b_verts)

            extruded_verts_last = []
            extruded_bm_verts_all = set()
            extruded_edges_last = []
            extruded_faces_last = []
            extruded_bm_faces_last = []

            matrix_spaces = [Matrix()]

            for idx in range(n_iterations):

                for item in extrude_geom:
                    if isinstance(item, bmesh.types.BMFace):
                        item[mask_layer] = OUT

                if is_290:
                    kwargs = {
                        'use_dissolve_ortho_edges': self.dissolve_ortho_edges
                    }
                else:
                    kwargs = {}

                new_geom = bmesh.ops.extrude_face_region(
                    bm,
                    geom=extrude_geom,
                    edges_exclude=set(),
                    use_keep_orig=self.keep_original,
                    **kwargs)['geom']

                extruded_verts = [
                    v for v in new_geom if isinstance(v, bmesh.types.BMVert)
                ]
                extruded_faces = [
                    f for f in new_geom if isinstance(f, bmesh.types.BMFace)
                ]

                if self.transform_mode == "Matrix":
                    matrices = matrix_per_iteration[idx]
                    if isinstance(matrices, Matrix):
                        matrices = [matrices]
                    matrix_spaces_matched = repeat_last_for_length(
                        matrix_spaces, len(extruded_verts))
                    for vertex_idx, (vertex, matrix) in enumerate(
                            zip(*match_long_repeat([extruded_verts, matrices
                                                    ]))):
                        bmesh.ops.transform(
                            bm,
                            verts=[vertex],
                            matrix=matrix,
                            space=matrix_spaces_matched[vertex_idx])
                        matrix_spaces_matched[vertex_idx] = matrix.inverted(
                        ) @ matrix_spaces_matched[vertex_idx]
                else:
                    height = height_per_iteration_matched[idx]
                    scale = scale_per_iteration_matched[idx]

                    normal = get_avg_normal(extruded_faces)
                    dr = normal * height
                    center = get_faces_center(extruded_faces)
                    translation = Matrix.Translation(center)
                    rotation = normal.rotation_difference(
                        (0, 0, 1)).to_matrix().to_4x4()
                    m = translation @ rotation
                    bmesh.ops.scale(bm,
                                    vec=(scale, scale, scale),
                                    space=m.inverted(),
                                    verts=extruded_verts)
                    bmesh.ops.translate(bm, verts=extruded_verts, vec=dr)

                extruded_bm_verts_all.update(extruded_verts)
                extruded_verts_last = [tuple(v.co) for v in extruded_verts]

                extruded_edges = [
                    e for e in new_geom if isinstance(e, bmesh.types.BMEdge)
                ]
                extruded_edges_last = [
                    tuple(v.index for v in edge.verts)
                    for edge in extruded_edges
                ]

                extruded_bm_faces_last = extruded_faces
                extruded_faces_last = [[v.index for v in face.verts]
                                       for face in extruded_faces]

                extrude_geom = new_geom

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []

            if need_mask_out:
                new_mask = self.get_out_mask(bm, extruded_bm_faces_last,
                                             extruded_bm_verts_all)
                result_mask.append(new_mask)

            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_ext_vertices.append(extruded_verts_last)
            result_ext_edges.append(extruded_edges_last)
            result_ext_faces.append(extruded_faces_last)
            result_face_data.append(new_face_data)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        self.outputs['NewVertices'].sv_set(result_ext_vertices)
        self.outputs['NewEdges'].sv_set(result_ext_edges)
        self.outputs['NewFaces'].sv_set(result_ext_faces)
        if 'Mask' in self.outputs:
            self.outputs['Mask'].sv_set(result_mask)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(result_face_data)
Beispiel #43
0
 def process(self):
     if not any(output.is_linked for output in self.outputs):
         return
     InVert, InEdge, InEdSel = self.inputs
     OutVert, OutEdg, OutFace, ONVert, ONEdg, ONFace, OOVert, OOEdg, OOFace = self.outputs
     vertices_s = InVert.sv_get(deepcopy=False)
     topo = InEdge.sv_get(deepcopy=False)
     if len(topo[0][0]) == 2:
         bmlist = [
             bmesh_from_pydata(v, e, [], normal_update=True)
             for v, e in zip(vertices_s, topo)
         ]
     else:
         bmlist = [
             bmesh_from_pydata(v, [], e, normal_update=True)
             for v, e in zip(vertices_s, topo)
         ]
     rev, ree, ref, riv, rie, rif, rsv, rse, rsf = [],[],[],[],[],[],[],[],[]
     if InEdSel.is_linked:
         if self.sel_mode == "index":
             useedges = [
                 np.array(bm.edges[:])[idxs]
                 for bm, idxs in zip(bmlist, InEdSel.sv_get(deepcopy=False))
             ]
         elif self.sel_mode == "mask":
             useedges = [
                 np.extract(mask, bm.edges[:])
                 for bm, mask in zip(bmlist, InEdSel.sv_get(deepcopy=False))
             ]
     else:
         useedges = [bm.edges for bm in bmlist]
     for bm, ind in zip(bmlist, useedges):
         geom = subdivide_edges(bm,
                                edges=ind,
                                smooth=self.smooth,
                                smooth_falloff=self.falloff_type,
                                fractal=self.fractal,
                                along_normal=self.along_normal,
                                cuts=self.cuts,
                                seed=self.seed,
                                quad_corner_type=self.corner_type,
                                use_grid_fill=self.grid_fill,
                                use_single_edge=self.single_edge,
                                use_only_quads=self.only_quads,
                                use_smooth_even=self.smooth_even)
         new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
         rev.append(new_verts)
         ree.append(new_edges)
         ref.append(new_faces)
         if self.show_new:
             geo1 = geom['geom_inner']
             riv.append([
                 tuple(v.co) for v in geo1
                 if isinstance(v, bmesh.types.BMVert)
             ])
             rie.append([[v.index for v in e.verts] for e in geo1
                         if isinstance(e, bmesh.types.BMEdge)])
             rif.append([[v.index for v in f.verts] for f in geo1
                         if isinstance(f, bmesh.types.BMFace)])
         if self.show_old:
             geo2 = geom['geom_split']
             rsv.append([
                 tuple(v.co) for v in geo2
                 if isinstance(v, bmesh.types.BMVert)
             ])
             rse.append([[v.index for v in e.verts] for e in geo2
                         if isinstance(e, bmesh.types.BMEdge)])
             rsf.append([[v.index for v in f.verts] for f in geo2
                         if isinstance(f, bmesh.types.BMFace)])
         bm.free()
     OutVert.sv_set(rev)
     OutEdg.sv_set(ree)
     OutFace.sv_set(ref)
     ONVert.sv_set(riv)
     ONEdg.sv_set(rie)
     ONFace.sv_set(rif)
     OOVert.sv_set(rsv)
     OOEdg.sv_set(rse)
     OOFace.sv_set(rsf)
Beispiel #44
0
    def process(self):
        if not any(s.is_linked for s in self.outputs):
            return

        verts_in = self.inputs['Vertices'].sv_get()
        edges_in = self.inputs['Edges'].sv_get()
        offset_in = self.inputs['Offset'].sv_get()
        step_in = self.inputs['Step'].sv_get()
        n_connections_in = self.inputs['NConnections'].sv_get()
        max_rhos_in = self.inputs['MaxRho'].sv_get()
        count_in = self.inputs['Count'].sv_get()
        length_in = self.inputs['Length'].sv_get()
        if self.z_mode == 'CURVE':
            curves_in = self.inputs['Curve'].sv_get()
        else:
            curves_in = [[]]

        verts_out = []
        edges_out = []
        faces_out = []

        Z = self.get_orientation_vector()
        if self.z_mode == 'AXIS':
            z_idx = 'XYZ'.index(self.orient_axis)
        else:
            z_idx = None

        objects = match_long_repeat([
            verts_in, edges_in, offset_in, step_in, n_connections_in,
            max_rhos_in, count_in, length_in, curves_in
        ])
        for verts, edges, offsets, steps, n_connections, max_rhos, counts, lengths, curves in zip(
                *objects):
            nverts = len(verts)
            offsets = cycle_for_length(offsets, nverts)
            steps = cycle_for_length(steps, nverts)
            n_connections = cycle_for_length(n_connections, nverts)
            max_rhos = cycle_for_length(max_rhos, nverts)
            if self.len_mode == 'COUNT':
                counts = cycle_for_length(counts, nverts)
                lengths = [None for i in range(nverts)]
            else:
                counts = [None for i in range(nverts)]
                lengths = cycle_for_length(lengths, nverts)

            if curves:
                curves = cycle_for_length(curves, nverts)

            bm = bmesh.new()
            bm.verts.ensure_lookup_table()

            verts_bm = []
            for i, v in enumerate(verts):
                if self.z_mode == 'AXIS':
                    verts_line = make_verts_axis(v, Z, self.make_basis,
                                                 steps[i] * offsets[i],
                                                 steps[i], counts[i],
                                                 lengths[i])
                else:
                    verts_line = make_verts_curve(v, curves[i])
                verts_line_bm = []
                prev_bm_vert = None
                new_vert = bm.verts.new
                new_edge = bm.edges.new
                for v in verts_line:
                    bm_vert = new_vert(v)
                    verts_line_bm.append(bm_vert)
                    bm.verts.ensure_lookup_table()
                    if prev_bm_vert is not None:
                        new_edge((prev_bm_vert, bm_vert))
                    prev_bm_vert = bm_vert
                verts_bm.append(verts_line_bm)

            for i, j in edges:
                process_edge(bm, z_idx, verts_bm[i], verts_bm[j], steps[i],
                             steps[j], n_connections[i], n_connections[j],
                             max_rhos[i], max_rhos[j])

            verts_new, edges_new, _ = pydata_from_bmesh(bm)
            bm.free()

            verts_new, edges_new = intersect_edges_3d(verts_new, edges_new,
                                                      1e-3)
            verts_new, edges_new, _ = remove_doubles(verts_new, edges_new, [],
                                                     1e-3)

            if self.outputs['Faces'].is_linked:
                bm = bmesh_from_pydata(verts_new,
                                       edges_new, [],
                                       normal_update=True)
                if self.z_mode == 'AXIS':
                    for i, j in edges:
                        side_edges = []
                        v_i = Vector(verts[i])
                        v_j = Vector(verts[j])
                        #self.info("Check: [%s - %s]", v_i, v_j)
                        for bm_edge in bm.edges:
                            bm_v1 = bm_edge.verts[0].co
                            bm_v2 = bm_edge.verts[1].co
                            if self.is_same_edge(bm_v1, bm_v2, v_i, v_j):
                                side_edges.append(bm_edge)
                                #self.info("Yes: [%s - %s]", bm_v1, bm_v2)
                            else:
                                pass
                                #self.info("No: [%s - %s]", bm_v1, bm_v2)

                        bmesh.ops.holes_fill(bm, edges=side_edges, sides=4)
                        bm.edges.ensure_lookup_table()
                        bm.faces.ensure_lookup_table()
                else:
                    bmesh.ops.holes_fill(bm, edges=bm.edges[:], sides=4)

                verts_new, edges_new, faces_new = pydata_from_bmesh(bm)
                bm.free()
            else:
                faces_new = []

            verts_out.append(verts_new)
            edges_out.append(edges_new)
            faces_out.append(faces_new)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
Beispiel #45
0
    def process(self):
        # inputs
        if not (self.inputs['Vertices'].is_linked):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edg_Pol'].sv_get(default=[[]])
        #faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        matrices_s = self.inputs['Matrices'].sv_get(default=[[]])
        if is_matrix(matrices_s[0]):
            matrices_s = [Matrix_generate(matrices_s)]
        else:
            matrices_s = [Matrix_generate(matrices) for matrices in matrices_s]
        #extrude_edges_s = self.inputs['ExtrudeEdges'].sv_get(default=[[]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_ext_vertices = []
        result_ext_edges = []
        result_ext_faces = []

        meshes = match_long_repeat([vertices_s, edges_s, matrices_s]) #, extrude_edges_s])
        
        for vertices, edges, matrices in zip(*meshes):
            if len(edges[0]) == 2:
                faces = []
            else:
                faces = edges.copy()
                edges = []
            if not matrices:
                matrices = [Matrix()]
            
            bm = bmesh_from_pydata(vertices, edges, faces)
            # better to do it in separate node, not integrate by default.
            #if extrude_edges:
            #    b_edges = []
            #    for edge in extrude_edges:
            #        b_edge = [e for e in bm.edges if set([v.index for v in e.verts]) == set(edge)]
            #        b_edges.append(b_edge[0])
            #else:
            b_edges = bm.edges

            new_geom = bmesh.ops.extrude_edge_only(bm, edges=b_edges, use_select_history=False)['geom']

            extruded_verts = [v for v in new_geom if isinstance(v, bmesh.types.BMVert)]

            for vertex, matrix in zip(*match_long_repeat([extruded_verts, matrices])):
                bmesh.ops.transform(bm, verts=[vertex], matrix=matrix, space=Matrix())

            extruded_verts = [tuple(v.co) for v in extruded_verts]

            extruded_edges = [e for e in new_geom if isinstance(e, bmesh.types.BMEdge)]
            extruded_edges = [tuple(v.index for v in edge.verts) for edge in extruded_edges]

            extruded_faces = [f for f in new_geom if isinstance(f, bmesh.types.BMFace)]
            extruded_faces = [[v.index for v in edge.verts] for edge in extruded_faces]

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_ext_vertices.append(extruded_verts)
            result_ext_edges.append(extruded_edges)
            result_ext_faces.append(extruded_faces)

        if self.outputs['Vertices'].is_linked:
            self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['NewVertices'].is_linked:
            self.outputs['NewVertices'].sv_set(result_ext_vertices)
        if self.outputs['NewEdges'].is_linked:
            self.outputs['NewEdges'].sv_set(result_ext_edges)
        if self.outputs['NewFaces'].is_linked:
            self.outputs['NewFaces'].sv_set(result_ext_faces)
Beispiel #46
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        obj_vertices_s = self.inputs['ObjVertices'].sv_get()
        obj_edges_s = self.inputs['ObjEdges'].sv_get(default=[[]])
        obj_faces_s = self.inputs['ObjFaces'].sv_get()
        surf_vertices_s = self.inputs['SurfVertices'].sv_get()
        surf_edges_s = self.inputs['SurfEdges'].sv_get(default=[[]])
        surf_faces_s = self.inputs['SurfFaces'].sv_get()
        fill_sides_s = self.inputs['FillSides'].sv_get()

        def remember_connection(edges_by_face, bm_edge, bm_intersection):
            for face in bm_edge.link_faces:
                edges_by_face[face].append((bm_intersection, bm_edge.index))

        cut_verts_out = []
        cut_edges_out = []
        cut_faces_out = []
        obj_verts_out = []
        obj_edges_out = []
        obj_faces_out = []
        inputs = zip_long_repeat(obj_vertices_s, obj_edges_s, obj_faces_s, surf_vertices_s, surf_edges_s, surf_faces_s, fill_sides_s)
        for obj_vertices, obj_edges, obj_faces, surf_vertices, surf_edges, surf_faces, fill_sides in inputs:
            if self.fill:
                if isinstance(fill_sides, (list, tuple)):
                    fill_sides = fill_sides[0]

            # We are using bvh's raycast to calculate intersections of object's edges
            # with the surface.
            bvh = mathutils.bvhtree.BVHTree.FromPolygons(surf_vertices, surf_faces)
            bm_obj = bmesh_from_pydata(obj_vertices, obj_edges, obj_faces)
            bm_cut = bmesh.new()
            edges_by_face = defaultdict(list)
            bm_obj.verts.index_update()
            bm_obj.edges.index_update()
            for bm_edge in bm_obj.edges:
                v1, v2 = bm_edge.verts
                edge = v1.co - v2.co
                # Distance restriction is used to find only intersections which are within the edge,
                # not anywhere on the ray.
                distance = edge.length

                # Since raycast's ray is single-directioned, we have to check for intersections
                # twice: from V1 to V2 and from V2 to V1.
                cast = bvh.ray_cast(v1.co, -edge, distance)
                #self.debug("Edge %s: %s -> %s, Cast 0: %s", bm_edge.index, v1.co, edge, cast)
                intersection = cast[0]
                if intersection is not None: 
                    bm_intersection = bm_cut.verts.new(intersection)
                    remember_connection(edges_by_face, bm_edge, bm_intersection)
                else:
                    cast = bvh.ray_cast(v2.co, edge, distance)
                    #self.debug("Edge %s: %s -> %s, Cast 1: %s", bm_edge.index, v2.co, -edge, cast)
                    intersection = cast[0]
                    if intersection is not None: 
                        bm_intersection = bm_cut.verts.new(intersection)
                        remember_connection(edges_by_face, bm_edge, bm_intersection)

            bm_cut.verts.index_update()

            # Make "cut surface" object.
            # Of each object's face we are cutting, make an edge.
            bm_cut_edges = []
            for intersections in edges_by_face.values():
                if len(intersections) == 1:
                    self.debug("Only one of object face's edges intersects the surface")
                    continue
                if len(intersections) > 2:
                    # Some day we may support splitting the face in more than two pieces;
                    # but the algorithm will be more complicated then.
                    raise Exception("Unsupported: more than two edges of the face intersect the surface")
                v1, v2 = intersections[0][0], intersections[1][0]
                bm_edge = bm_cut.edges.new((v1, v2))
                bm_cut_edges.append(bm_edge)

            if len(bm_cut.verts) > 0:
                if self.fill:
                    bmesh.ops.holes_fill(bm_cut, edges=bm_cut_edges, sides=fill_sides)

            new_verts_cut, new_edges_cut, new_faces_cut = pydata_from_bmesh(bm_cut)

            if self.make_pieces:
                new_verts_by_old_edge = dict()
                new_verts_by_old_face = dict()
                for old_obj_face in edges_by_face:
                    intersections = edges_by_face[old_obj_face]
                    if len(intersections) == 1:
                        continue
                    int1, int2 = intersections 
                    intersection1, intersection2 = int1[0].co, int2[0].co
                    old_edge1, old_edge2 = int1[1], int2[1]
                    # Create a vertex in the "object" mesh at each intersection of
                    # it's edge with the surface.
                    # Remember which of new vertices corresponds to which edge.
                    if old_edge1 not in new_verts_by_old_edge:
                        new_vert_1 = bm_obj.verts.new(intersection1)
                        new_verts_by_old_edge[old_edge1] = new_vert_1
                    else:
                        new_vert_1 = new_verts_by_old_edge[old_edge1]
                    if old_edge2 not in new_verts_by_old_edge:
                        new_vert_2 = bm_obj.verts.new(intersection2)
                        new_verts_by_old_edge[old_edge2] = new_vert_2
                    else:
                        new_vert_2 = new_verts_by_old_edge[old_edge2]
                    new_verts_by_old_face[old_obj_face] = (new_vert_1, new_vert_2)
                    bm_obj.verts.index_update()

                faces_to_remove = []
                edges_to_remove = []
                for old_obj_face in edges_by_face:
                    intersections = edges_by_face[old_obj_face]
                    if len(intersections) == 1:
                        continue

                    # Walk through the edges of each face we are cutting, in order.
                    # Of each such face, we are making two. So in this loop we have
                    # two states: new_face_state == True means we are on the one side of
                    # the cut, False means we are on the another. Note that we do not know
                    # which is which (for example, which one is "inside" the surface); but
                    # it does not matter for us.
                    # So new_face_verts[True] will contain vertices of one piece,
                    # new_face_verts[False] - of another one.
                    new_face_verts = defaultdict(list)
                    new_face_side = True
                    old_vert_pairs = list(zip(old_obj_face.verts, old_obj_face.verts[1:])) + [(old_obj_face.verts[-1], old_obj_face.verts[0])]
                    need_split = False
                    for old_vert_1, old_vert_2 in old_vert_pairs:
                        old_edge = bm_obj.edges.get((old_vert_1, old_vert_2))
                        if old_edge.index in new_verts_by_old_edge:
                            edges_to_remove.append((old_edge.verts[0], old_edge.verts[1]))
                            need_split = True
                            new_vert_1 = new_verts_by_old_edge[old_edge.index]
                            self.debug("Old edge %s - %s is to be split; use new vert %s", old_vert_1.index, old_vert_2.index, new_vert_1.index)
                            new_face_verts[new_face_side].append(new_vert_1)
                            # if this edge is to be split, then we are stepping from one piece of
                            # the face to another
                            new_face_side = not new_face_side
                            new_face_verts[new_face_side].append(new_vert_1)
                            new_face_verts[new_face_side].append(old_vert_2)
                        else:
                            self.debug("Old edge %s - %s is not to be split", old_vert_1.index, old_vert_2.index)
                            new_face_verts[new_face_side].append(old_vert_2)

                    if need_split:
                        faces_to_remove.append(old_obj_face)
                        self.debug("Splitting face: %s", [v.index for v in old_obj_face.verts])
                        for new_face_list in new_face_verts.values():
                            bm_obj.faces.new(new_face_list)

                # remove old faces and edges (ones we cut in two)
                for old_face in faces_to_remove:
                    bm_obj.faces.remove(old_face)
                for old_v1, old_v2 in edges_to_remove:
                    # we can't just remember BMEdge instances themselves,
                    # since they will be invalidated when we remove faces.
                    old_edge = bm_obj.edges.get((old_v1, old_v2))
                    if old_edge:
                        bm_obj.edges.remove(old_edge)

                edges_to_split = []
                for new_vert_1, new_vert_2 in new_verts_by_old_face.values():
                    edge = bm_obj.edges.get((new_vert_1, new_vert_2))
                    edges_to_split.append(edge)

                # Split "object" by remembered cut edges. There will be "holes"
                # at places we cut.
                split_result = bmesh.ops.split_edges(bm_obj, edges=edges_to_split)
                if self.fill:
                    bmesh.ops.holes_fill(bm_obj, edges = split_result['edges'], sides=fill_sides)

                new_verts_obj, new_edges_obj, new_faces_obj = pydata_from_bmesh(bm_obj)
            else:
                new_verts_obj, new_edges_obj, new_faces_obj = [], [], []

            bm_cut.free()
            bm_obj.free()

            cut_verts_out.append(new_verts_cut)
            cut_edges_out.append(new_edges_cut)
            cut_faces_out.append(new_faces_cut)
            obj_verts_out.append(new_verts_obj)
            obj_edges_out.append(new_edges_obj)
            obj_faces_out.append(new_faces_obj)

        self.outputs['CutVertices'].sv_set(cut_verts_out)
        self.outputs['CutEdges'].sv_set(cut_edges_out)
        self.outputs['CutFaces'].sv_set(cut_faces_out)
        self.outputs['ObjVertices'].sv_set(obj_verts_out)
        self.outputs['ObjEdges'].sv_set(obj_edges_out)
        self.outputs['ObjFaces'].sv_set(obj_faces_out)
    def process(self):
        # inputs
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not any(
                self.outputs[name].is_linked for name in
            ['Vertices', 'Edges', 'Polygons', 'ExtrudedPolys', 'OtherPolys']):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        masks_s = self.inputs['Mask'].sv_get(default=[[1]])
        heights_s = self.inputs['Height'].sv_get()
        scales_s = self.inputs['Scale'].sv_get()

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s])

        offset = 0
        for vertices, edges, faces, masks, heights, scales in zip(*meshes):
            fullList(heights, len(faces))
            fullList(scales, len(faces))
            fullList(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces)
            extruded_faces = bmesh.ops.extrude_discrete_faces(
                bm, faces=bm.faces)['faces']

            new_extruded_faces = []

            for face, mask, height, scale in zip(extruded_faces, masks,
                                                 heights, scales):
                if not mask:
                    continue
                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                rotation = face.normal.rotation_difference(
                    (0, 0, 1)).to_matrix().to_4x4()
                #rotation = autorotate(z, face.normal).inverted()
                m = translation * rotation
                bmesh.ops.scale(bm,
                                vec=(scale, scale, scale),
                                space=m.inverted(),
                                verts=face.verts)
                bmesh.ops.translate(bm, verts=face.verts, vec=dr)

                new_extruded_faces.append([v.index for v in face.verts])

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()
            new_other_faces = [
                f for f in new_faces if f not in new_extruded_faces
            ]

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['ExtrudedPolys'].is_linked:
            self.outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        if self.outputs['OtherPolys'].is_linked:
            self.outputs['OtherPolys'].sv_set(result_other_faces)
    def process(self):
        # inputs
        if not self.inputs['Vertices'].is_linked:
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        masks_s = self.inputs['Mask'].sv_get(default=[[1]])
        if self.transform_mode == "Matrix":
            matrices_s = [self.inputs['Matrices'].sv_get(Matrix())]
            heights_s = [0.0]
            scales_s = [1.0]
        else:
            matrices_s = [[]]
            heights_s = self.inputs['Height'].sv_get()
            scales_s = self.inputs['Scale'].sv_get()

        result_vertices = []
        result_edges = []
        result_faces = []
        result_ext_vertices = []
        result_ext_edges = []
        result_ext_faces = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s,
            scales_s
        ])

        for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration in zip(
                *meshes):
            if self.transform_mode == "Matrix":
                if not matrix_per_iteration:
                    matrix_per_iteration = [Matrix()]

            if self.multiple:
                if self.transform_mode == "Matrix":
                    n_iterations = len(matrix_per_iteration)
                else:
                    n_iterations = max(len(height_per_iteration),
                                       len(scale_per_iteration))
                    fullList(height_per_iteration, n_iterations)
                    fullList(scale_per_iteration, n_iterations)
            else:
                n_iterations = 1
                matrix_per_iteration = [matrix_per_iteration]

            fullList(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)

            b_faces = []
            b_edges = set()
            b_verts = set()
            for mask, face in zip(masks, bm.faces):
                if mask:
                    b_faces.append(face)
                    for edge in face.edges:
                        b_edges.add(edge)
                    for vert in face.verts:
                        b_verts.add(vert)

            extrude_geom = b_faces + list(b_edges) + list(b_verts)

            extruded_verts_last = []
            extruded_edges_last = []
            extruded_faces_last = []

            matrix_spaces = [Matrix()]

            for idx in range(n_iterations):

                new_geom = bmesh.ops.extrude_face_region(
                    bm,
                    geom=extrude_geom,
                    edges_exclude=set(),
                    use_keep_orig=self.keep_original)['geom']

                extruded_verts = [
                    v for v in new_geom if isinstance(v, bmesh.types.BMVert)
                ]
                extruded_faces = [
                    f for f in new_geom if isinstance(f, bmesh.types.BMFace)
                ]

                if self.transform_mode == "Matrix":
                    matrices = matrix_per_iteration[idx]
                    if isinstance(matrices, Matrix):
                        matrices = [matrices]
                    fullList(matrix_spaces, len(extruded_verts))
                    for vertex_idx, (vertex, matrix) in enumerate(
                            zip(*match_long_repeat([extruded_verts, matrices
                                                    ]))):
                        bmesh.ops.transform(bm,
                                            verts=[vertex],
                                            matrix=matrix,
                                            space=matrix_spaces[vertex_idx])
                        matrix_spaces[vertex_idx] = matrix.inverted(
                        ) @ matrix_spaces[vertex_idx]
                else:
                    height = height_per_iteration[idx]
                    scale = scale_per_iteration[idx]

                    normal = get_avg_normal(extruded_faces)
                    dr = normal * height
                    center = get_faces_center(extruded_faces)
                    translation = Matrix.Translation(center)
                    rotation = normal.rotation_difference(
                        (0, 0, 1)).to_matrix().to_4x4()
                    m = translation @ rotation
                    bmesh.ops.scale(bm,
                                    vec=(scale, scale, scale),
                                    space=m.inverted(),
                                    verts=extruded_verts)
                    bmesh.ops.translate(bm, verts=extruded_verts, vec=dr)

                extruded_verts_last = [tuple(v.co) for v in extruded_verts]

                extruded_edges = [
                    e for e in new_geom if isinstance(e, bmesh.types.BMEdge)
                ]
                extruded_edges_last = [
                    tuple(v.index for v in edge.verts)
                    for edge in extruded_edges
                ]

                extruded_faces_last = [[v.index for v in edge.verts]
                                       for edge in extruded_faces]

                extrude_geom = new_geom

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_ext_vertices.append(extruded_verts_last)
            result_ext_edges.append(extruded_edges_last)
            result_ext_faces.append(extruded_faces_last)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        self.outputs['NewVertices'].sv_set(result_ext_vertices)
        self.outputs['NewEdges'].sv_set(result_ext_edges)
        self.outputs['NewFaces'].sv_set(result_ext_faces)
Beispiel #49
0
    def process(self):

        inputs = self.inputs
        outputs = self.outputs

        if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked):
            return
        if not any(socket.is_linked for socket in outputs):
            return

        need_mask_out = 'Mask' in outputs and outputs['Mask'].is_linked

        vector_in = self.scale_socket_type

        vertices_s = inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        masks_s = inputs['Mask'].sv_get(default=[[1]], deepcopy=False)
        heights_s = inputs['Height'].sv_get(deepcopy=False)
        scales_s  = inputs['Scale'].sv_get(deepcopy=False)
        if 'Matrix' in inputs:
            matrixes_s = inputs['Matrix'].sv_get(default=[[Matrix()]], deepcopy=False)
        else:
            matrixes_s = [[Matrix()]]
        if 'FaceData' in inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]], deepcopy=False)
        else:
            face_data_s = [[]]

        if type(matrixes_s[0]) == Matrix:
            matrixes_s = [matrixes_s]

        linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
        linked_other_polygons = outputs['OtherPolys'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []
        result_mask = []
        result_face_data = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s, matrixes_s, face_data_s])

        for vertices, edges, faces, masks_, heights_, scales_, matrixes_, face_data in zip(*meshes):

            new_extruded_faces = []
            new_extruded_faces_append = new_extruded_faces.append
            heights, scales, matrixes = make_repeaters([heights_, scales_, matrixes_])
            masks = repeat_last_for_length(masks_, len(faces))
            if face_data:
                face_data_matched = repeat_last_for_length(face_data, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True, normal_update=True)
            mask_layer = bm.faces.layers.int.new('mask')
            bm.faces.ensure_lookup_table()
            fill_faces_layer(bm, masks, 'mask', int, OUT)

            if self.mask_mode == 'NOEXTRUDE':
                faces_to_extrude = [face for face, mask in zip(bm.faces, masks) if mask]
            else:
                faces_to_extrude = bm.faces

            extruded_faces = bmesh.ops.extrude_discrete_faces(bm, faces=faces_to_extrude)['faces']

            if self.mask_mode == 'NOEXTRUDE':
                extruded_face_items = zip(extruded_faces, heights, scales, matrixes)
            else:
                extruded_face_items = [(face, height, scale, matrix) for (face, mask, height, scale, matrix) in zip(extruded_faces, masks, heights, scales, matrixes) if mask]

            for face, height, scale, matrix in extruded_face_items:

                vec = scale if vector_in else (scale, scale, scale)

                # preparing matrix
                normal = face.normal
                if normal[0] == 0 and normal[1] == 0:
                    m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(pi, 4, 'X')
                else:
                    z_axis = normal
                    x_axis = (Vector((z_axis[1] * -1, z_axis[0], 0))).normalized()
                    y_axis = (z_axis.cross(x_axis)).normalized()
                    m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])])).to_4x4()

                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                space = (translation @ m_r).inverted()

                if self.extrude_mode == 'NORMAL':
                    # inset, scale and push operations
                    bmesh.ops.scale(bm, vec=vec, space=space, verts=face.verts)
                    bmesh.ops.translate(bm, verts=face.verts, vec=dr)
                else:
                    bmesh.ops.transform(bm, matrix=matrix, space=space, verts=face.verts)

                if linked_extruded_polygons or linked_other_polygons:
                    new_extruded_faces_append([v.index for v in face.verts])

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []

            new_other_faces = [f for f in new_faces if f not in new_extruded_faces] if linked_other_polygons else []
            if need_mask_out:
                new_mask = self.get_out_mask(bm, extruded_faces)
                result_mask.append(new_mask)

            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)
            result_face_data.append(new_face_data)

        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Polygons'].sv_set(result_faces)
        outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        outputs['OtherPolys'].sv_set(result_other_faces)
        if need_mask_out:
            outputs['Mask'].sv_set(result_mask)
        if 'FaceData' in outputs:
            outputs['FaceData'].sv_set(result_face_data)
Beispiel #50
0
    def process(self):
        # достаём два слота - вершины и полики
        if all(s.is_linked for s in self.inputs[:-1]):
            if self.inputs['Z_Coef'].is_linked:
                z_coef = self.inputs['Z_Coef'].sv_get()[0]
            else:
                z_coef = []

            polsR = self.inputs['PolsR'].sv_get()[
                0]  # recipient one object [0]
            versR = self.inputs['VersR'].sv_get()[0]  # recipient
            polsD = self.inputs['PolsD'].sv_get()  # donor many objects [:]
            versD_ = self.inputs['VersD'].sv_get()  # donor
            versD = Vector_generate(versD_)
            polsR, polsD, versD = match_long_repeat([polsR, polsD, versD])

            bm = bmesh_from_pydata(versR, [], polsR, normal_update=True)
            bm.verts.ensure_lookup_table()
            new_ve = bm.verts

            vers_out = []
            pols_out = []
            i = 0
            for vD, pR in zip(versD, polsR):
                # part of donor to make limits
                j = i
                pD = polsD[i]

                xx = [x[0] for x in vD]
                x0 = (self.width_coef) / (max(xx) - min(xx))
                yy = [y[1] for y in vD]
                y0 = (self.width_coef) / (max(yy) - min(yy))
                zz = [z[2] for z in vD]
                zzz = (max(zz) - min(zz))
                if zzz:
                    z0 = 1 / zzz
                else:
                    z0 = 0

                # part of recipient polygons to reciev donor
                last = len(pR) - 1
                vs = [new_ve[v] for v in pR]  # new_ve  - temporery data
                if z_coef:
                    if j < len(z_coef):
                        z1 = z0 * z_coef[j]
                else:
                    z1 = z0

                new_vers = []
                new_pols = []
                for v in vD:
                    new_vers.append(
                        self.lerp3(vs[0], vs[1], vs[2], vs[last], v, x0, y0,
                                   z1))
                for p in pD:
                    new_pols.append([id for id in p])
                pols_out.append(new_pols)
                vers_out.append(new_vers)
                i += 1

            bm.free()
            output = Vector_degenerate(vers_out)

            self.outputs['Vertices'].sv_set(output)
            self.outputs['Poligons'].sv_set(pols_out)
    def process(self):
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not (any(
                self.outputs[name].is_linked for name in
            ['Vertices', 'Edges', 'Polygons', 'NewEdges', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]])
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        mask_s = self.inputs['Mask'].sv_get(default=[[True]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_new_edges = []
        result_new_faces = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, mask_s])

        for vertices, edges, faces, mask in zip(*meshes):

            bm = bmesh_from_pydata(vertices, edges, faces)
            fullList(mask, len(faces))

            b_faces = []
            for m, face in zip(mask, bm.faces):
                if m:
                    b_faces.append(face)

            res = bmesh.ops.triangulate(bm,
                                        faces=b_faces,
                                        quad_method=int(self.quad_mode),
                                        ngon_method=int(self.ngon_mode))

            b_new_edges = [
                tuple(v.index for v in edge.verts) for edge in res['edges']
            ]
            b_new_faces = [[v.index for v in face.verts]
                           for face in res['faces']]

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_new_edges.append(b_new_edges)
            result_new_faces.append(b_new_faces)

        if self.outputs['Vertices'].is_linked:
            self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['NewEdges'].is_linked:
            self.outputs['NewEdges'].sv_set(result_new_edges)
        if self.outputs['NewPolys'].is_linked:
            self.outputs['NewPolys'].sv_set(result_new_faces)
    def process(self):
        # достаём два слота - вершины и полики
        if 'Vertices' in self.outputs and self.outputs['Vertices'].links:
            if (self.inputs['PolsR'].links and self.inputs['VersR'].links
                    and self.inputs['VersD'].links
                    and self.inputs['PolsD'].links):

                if self.inputs['Z_Coef'].links:
                    z_coef = SvGetSocketAnyType(self, self.inputs['Z_Coef'])[0]
                else:
                    z_coef = []

                polsR = SvGetSocketAnyType(
                    self, self.inputs['PolsR'])[0]  # recipient one object [0]
                versR = SvGetSocketAnyType(
                    self, self.inputs['VersR'])[0]  # recipient
                polsD = SvGetSocketAnyType(
                    self, self.inputs['PolsD'])  # donor many objects [:]
                versD_ = SvGetSocketAnyType(self,
                                            self.inputs['VersD'])  # donor
                versD = Vector_generate(versD_)
                ##### it is needed for normals of vertices
                bm = bmesh_from_pydata(versR, [], polsR)

                bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
                bm.verts.ensure_lookup_table()
                new_ve = bm.verts

                #new_me = bpy.data.meshes.new('recepient')
                #new_me.from_pydata(versR, [], polsR)
                #new_me.update(calc_edges=True)

                #new_ve = new_me.vertices
                #print (new_ve[0].normal, 'normal')

                for i, vD in enumerate(versD):

                    pD = polsD[i]
                    n_verts = len(vD)
                    n_faces = len(pD)

                    xx = [x[0] for x in vD]
                    x0 = (self.width_coef) / (max(xx) - min(xx))
                    yy = [y[1] for y in vD]
                    y0 = (self.width_coef) / (max(yy) - min(yy))
                    zz = [z[2] for z in vD]
                    zzz = (max(zz) - min(zz))
                    if zzz:
                        z0 = 1 / zzz
                    else:
                        z0 = 0
                    #print (x0, y0, z0)

                    vers_out = []
                    pols_out = []

                    for j, pR in enumerate(polsR):

                        last = len(pR) - 1
                        vs = [new_ve[v]
                              for v in pR]  # new_ve  - temporery data
                        if z_coef:
                            if j < len(z_coef):
                                z1 = z0 * z_coef[j]
                        else:
                            z1 = z0

                        new_vers = []
                        new_pols = []
                        for v in vD:
                            new_vers.append(
                                self.lerp3(vs[0], vs[1], vs[2], vs[last], v,
                                           x0, y0, z1))
                        for p in pD:
                            new_pols.append([id for id in p])
                        pols_out.append(new_pols)
                        vers_out.append(new_vers)
                #bpy.data.meshes.remove(new_me)  # cleaning and washing
                bm.free()
                #print (Vector_degenerate(vers_out))

                output = Vector_degenerate(vers_out)
                #print (output)
                if 'Vertices' in self.outputs and self.outputs[
                        'Vertices'].links:
                    SvSetSocketAnyType(self, 'Vertices', output)

                if 'Poligons' in self.outputs and self.outputs[
                        'Poligons'].links:
                    SvSetSocketAnyType(self, 'Poligons', pols_out)
Beispiel #53
0
    def process(self):
        if not any(output.is_linked for output in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Faces'].sv_get(default=[[]])
        masks_s = self.inputs['EdgeMask'].sv_get(default=[[1]])

        cuts_s = self.inputs['Cuts'].sv_get()[0]
        smooth_s = self.inputs['Smooth'].sv_get()[0]
        fractal_s = self.inputs['Fractal'].sv_get()[0]
        along_normal_s = self.inputs['AlongNormal'].sv_get()[0]
        seed_s = self.inputs['Seed'].sv_get()[0]

        result_vertices = []
        result_edges = []
        result_faces = []

        r_inner_vertices = []
        r_inner_edges = []
        r_inner_faces = []

        r_split_vertices = []
        r_split_edges = []
        r_split_faces = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, cuts_s, smooth_s, fractal_s,
            along_normal_s, seed_s
        ])
        for vertices, edges, faces, masks, cuts, smooth, fractal, along_normal, seed in zip(
                *meshes):
            fullList(masks, len(edges))

            bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)

            selected_edges = []
            for m, edge in zip(masks, edges):
                if not m:
                    continue
                found = False
                for bmesh_edge in bm.edges:
                    if set(v.index for v in bmesh_edge.verts) == set(edge):
                        found = True
                        break
                if found:
                    selected_edges.append(bmesh_edge)
                else:
                    print("Cant find edge: " + str(edge))

            geom = bmesh.ops.subdivide_edges(
                bm,
                edges=selected_edges,
                smooth=smooth,
                smooth_falloff=int(self.falloff_type),
                fractal=fractal,
                along_normal=along_normal,
                cuts=cuts,
                seed=seed,
                quad_corner_type=int(self.corner_type),
                use_grid_fill=self.grid_fill,
                use_single_edge=self.single_edge,
                use_only_quads=self.only_quads,
                use_smooth_even=self.smooth_even)

            new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
            inner_verts, inner_edges, inner_faces = self.get_result_pydata(
                geom['geom_inner'])
            split_verts, split_edges, split_faces = self.get_result_pydata(
                geom['geom_split'])

            bm.free()

            result_vertices.append(new_verts)
            result_edges.append(new_edges)
            result_faces.append(new_faces)

            r_inner_vertices.append(inner_verts)
            r_inner_edges.append(inner_edges)
            r_inner_faces.append(inner_faces)

            r_split_vertices.append(split_verts)
            r_split_edges.append(split_edges)
            r_split_faces.append(split_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Faces'].sv_set(result_faces)

        self.outputs['NewVertices'].sv_set(r_inner_vertices)
        self.outputs['NewEdges'].sv_set(r_inner_edges)
        self.outputs['NewFaces'].sv_set(r_inner_faces)

        self.outputs['OldVertices'].sv_set(r_split_vertices)
        self.outputs['OldEdges'].sv_set(r_split_edges)
        self.outputs['OldFaces'].sv_set(r_split_faces)
Beispiel #54
0
def calc_mesh_normals(vertices, edges, faces):
    bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
    vertex_normals = [v.normal[:] for v in bm.verts]
    bm.free()
    return vertex_normals
Beispiel #55
0
    def process(self):

        inputs = self.inputs
        outputs = self.outputs

        if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked):
            return
        if not any(socket.is_linked for socket in outputs):
            return

        vector_in = self.scale_socket_type

        vertices_s = inputs['Vertices'].sv_get()
        edges_s = inputs['Edges'].sv_get(default=[[]])
        faces_s = inputs['Polygons'].sv_get(default=[[]])
        masks_s = inputs['Mask'].sv_get(default=[[1]])
        heights_s = inputs['Height'].sv_get()
        scales_s = inputs['Scale'].sv_get()

        linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
        linked_other_polygons = outputs['OtherPolys'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s])

        for vertices, edges, faces, masks, heights, scales in zip(*meshes):

            new_extruded_faces = []
            new_extruded_faces_append = new_extruded_faces.append
            fullList(heights, len(faces))
            fullList(scales, len(faces))
            fullList(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces)
            extruded_faces = bmesh.ops.extrude_discrete_faces(
                bm, faces=bm.faces)['faces']

            for face, mask, height, scale in zip(extruded_faces, masks,
                                                 heights, scales):

                if not mask:
                    continue

                vec = scale if vector_in else (scale, scale, scale)

                # preparing matrix
                normal = face.normal
                if normal[0] == 0 and normal[1] == 0:
                    m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(
                        pi, 4, 'X')
                else:
                    z_axis = normal
                    x_axis = (Vector(
                        (z_axis[1] * -1, z_axis[0], 0))).normalized()
                    y_axis = (z_axis.cross(x_axis)).normalized()
                    m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])
                                       ])).to_4x4()

                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                m = (translation @ m_r).inverted()

                # inset, scale and push operations
                bmesh.ops.scale(bm, vec=vec, space=m, verts=face.verts)
                bmesh.ops.translate(bm, verts=face.verts, vec=dr)

                if linked_extruded_polygons or linked_other_polygons:
                    new_extruded_faces_append([v.index for v in face.verts])

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            new_other_faces = [
                f for f in new_faces if f not in new_extruded_faces
            ] if linked_other_polygons else []

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)

        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Polygons'].sv_set(result_faces)
        outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        outputs['OtherPolys'].sv_set(result_other_faces)
Beispiel #56
0
    def process(self):
        bmL, V, E, P = self.inputs
        Val = bmL.sv_get() if bmL.is_linked else []
        o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25 = self.outputs
        if V.is_linked:
            for v, e, f in zip(*match_long_repeat(
                [V.sv_get(), E.sv_get([[]]),
                 P.sv_get([[]])])):
                bm = bmesh_from_pydata(v, e, f)
                Val.append(bm)

        if self.mode1:
            for bm in Val:
                bm.normal_update()

        if o1.is_linked:
            o1.sv_set([[bm.calc_volume(signed=False) for bm in Val]])

        if o2.is_linked:
            o2.sv_set([[vert.calc_edge_angle(-1) for vert in bm.verts]
                       for bm in Val])
        if o3.is_linked:
            o3.sv_set([[vert.calc_shell_factor() for vert in bm.verts]
                       for bm in Val])
        if o4.is_linked:
            o4.sv_set([[vert.is_boundary for vert in bm.verts] for bm in Val])
        if o5.is_linked:
            o5.sv_set([[vert.is_manifold for vert in bm.verts] for bm in Val])
        if o6.is_linked:
            o6.sv_set([[vert.is_wire for vert in bm.verts] for bm in Val])
        if o7.is_linked:
            o7.sv_set([[vert.normal[:] for vert in bm.verts] for bm in Val])

        if o8.is_linked:
            o8.sv_set([[edge.calc_face_angle_signed(0) for edge in bm.edges]
                       for bm in Val])
        if o9.is_linked:
            o9.sv_set([[edge.calc_length() for edge in bm.edges]
                       for bm in Val])
        if o10.is_linked:
            o10.sv_set([[edge.is_boundary for edge in bm.edges] for bm in Val])
        if o11.is_linked:
            o11.sv_set([[edge.is_contiguous for edge in bm.edges]
                        for bm in Val])
        if o12.is_linked:
            o12.sv_set([[edge.is_convex for edge in bm.edges] for bm in Val])
        if o13.is_linked:
            o13.sv_set([[edge.is_manifold for edge in bm.edges] for bm in Val])
        if o14.is_linked:
            o14.sv_set([[edge.is_wire for edge in bm.edges] for bm in Val])

        if o15.is_linked:
            o15.sv_set([[face.calc_area() for face in bm.faces] for bm in Val])
        if o16.is_linked:
            o16.sv_set([[face.calc_center_bounds()[:] for face in bm.faces]
                        for bm in Val])
        if o17.is_linked:
            o17.sv_set([[face.calc_center_median()[:] for face in bm.faces]
                        for bm in Val])
        if o18.is_linked:
            o18.sv_set(
                [[face.calc_center_median_weighted()[:] for face in bm.faces]
                 for bm in Val])
        if o19.is_linked:
            o19.sv_set([[face.calc_perimeter() for face in bm.faces]
                        for bm in Val])
        if o20.is_linked:
            o20.sv_set([[face.calc_tangent_edge()[:] for face in bm.faces]
                        for bm in Val])
        if o21.is_linked:
            o21.sv_set(
                [[face.calc_tangent_edge_diagonal()[:] for face in bm.faces]
                 for bm in Val])
        if o22.is_linked:
            o22.sv_set(
                [[face.calc_tangent_edge_pair()[:] for face in bm.faces]
                 for bm in Val])
        if o23.is_linked:
            o23.sv_set(
                [[face.calc_tangent_vert_diagonal()[:] for face in bm.faces]
                 for bm in Val])
        if o24.is_linked:
            o24.sv_set([[face.normal[:] for face in bm.faces] for bm in Val])

        if o25.is_linked:
            o25.sv_set(Val)
Beispiel #57
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            vertices_s = self.inputs['Vertices'].sv_get()
            edges_s = self.inputs['Edges'].sv_get()
            faces_s = self.inputs['Faces'].sv_get()
            vertex_weight_s = self.inputs['VertexWeight'].sv_get()
            edge_weight_s = self.inputs['EdgeWeight'].sv_get()
            face_weight_s = self.inputs['FaceWeight'].sv_get()
            tangent_weight_s = self.inputs['TangentWeight'].sv_get()
            degree_u_s = self.inputs['DegreeU'].sv_get()
            degree_v_s = self.inputs['DegreeV'].sv_get()

            surface_out = []
            control_points_out = []
            weights_out = []
            inputs = zip_long_repeat(vertices_s, edges_s, faces_s, degree_u_s,
                                     degree_v_s, vertex_weight_s,
                                     edge_weight_s, face_weight_s,
                                     tangent_weight_s)
            for vertices, edges, faces, degree_u, degree_v, vertex_weights, edge_weights, face_weights, tangent_weights in inputs:
                fullList(degree_u, len(faces))
                fullList(degree_v, len(faces))

                if not edges:
                    edges = polygons_to_edges([faces], True)[0]

                fullList(vertex_weights, len(vertices))
                fullList(tangent_weights, len(vertices))
                fullList(edge_weights, len(edges))
                fullList(face_weights, len(faces))

                bm = bmesh_from_pydata(vertices,
                                       edges,
                                       faces,
                                       normal_update=True,
                                       markup_edge_data=True)
                normals = [vertex.normal for vertex in bm.verts]
                edge_planes_dict = dict()
                for edge in bm.edges:
                    edge_v = edge.verts[1].co - edge.verts[0].co
                    edge_c = (edge.verts[0].co + edge.verts[1].co) / 2.0
                    edge_ort_plane = PlaneEquation.from_normal_and_point(
                        edge_v, edge_c)
                    face_normals = [face.normal for face in edge.link_faces]
                    faces_normal = sum(face_normals, Vector())
                    projected_faces_normal = edge_ort_plane.projection_of_point(
                        faces_normal)
                    #print("EV: %s, No.sum: %s, Pr.N: %s" % (edge_v, faces_normal, projected_faces_normal))
                    edge_plane = PlaneEquation.from_normal_and_point(
                        projected_faces_normal, edge_c)
                    edge_planes_dict[(edge.verts[0].index,
                                      edge.verts[1].index)] = edge_plane
                    edge_planes_dict[(edge.verts[1].index,
                                      edge.verts[0].index)] = edge_plane
                bm.free()

                vert_planes = [
                    PlaneEquation.from_normal_and_point(normal, point)
                    for normal, point in zip(normals, vertices)
                ]

                edge_weights_dict = dict()
                #edge_planes_dict = dict()
                for (i, j), edge_weight in zip(edges, edge_weights):
                    edge_weights_dict[(i, j)] = edge_weight
                    edge_weights_dict[(j, i)] = edge_weight
                    #edge_planes_dict[(i, j)] = edge_plane
                    #edge_planes_dict[(j, i)] = edge_plane

                for i, (face, degree_u, degree_v, face_weight) in enumerate(
                        zip(faces, degree_u, degree_v, face_weights)):
                    if len(face) != 4:
                        self.info("Face #%s is not a Quad, skip it", i)
                        continue
                    face_verts = [vertices[i] for i in face]
                    face_planes = [vert_planes[i] for i in face]
                    face_vert_weights = [vertex_weights[i] for i in face]
                    face_tangent_weights = [tangent_weights[i] for i in face]
                    #face_edges = list(zip(face, face[1:])) + [(face[-1], face[0])]
                    #face_edge_weights = [edge_weights_dict[edge] for edge in face_edges]
                    surface, ctrlpts, weights = self.make_surface(
                        face, degree_u, degree_v, face_verts, face_planes,
                        face_vert_weights, face_tangent_weights, face_weight,
                        edge_weights_dict, edge_planes_dict)
                    surface_out.append(surface)
                    control_points_out.append(list(map(tuple, ctrlpts)))
                    weights_out.append(weights)

            self.outputs['Surfaces'].sv_set(surface_out)
            self.outputs['ControlPoints'].sv_set(control_points_out)
            self.outputs['Weights'].sv_set(weights_out)
Beispiel #58
0
def make_bmesh_geometry_merged(node, obj_index, context, yielder_object):
    scene = context.scene
    collection = scene.collection
    meshes = bpy.data.meshes
    objects = bpy.data.objects
    name = f'{node.basedata_name}.{obj_index:04d}'

    if name in objects:
        sv_object = objects[name]
    else:
        temp_mesh = default_mesh(name)
        sv_object = objects.new(name, temp_mesh)
        collection.objects.link(sv_object)

    # book-keeping via ID-props!
    sv_object['idx'] = obj_index
    sv_object['madeby'] = node.name
    sv_object['basedata_name'] = node.basedata_name

    vert_count = 0
    big_verts = []
    big_edges = []
    big_faces = []
    big_materials = []

    for result in yielder_object:

        verts, topology = result
        edges, faces, materials, matrix = topology

        if matrix:
            # matrix = matrix_sanitizer(matrix)
            verts = [matrix @ Vector(v) for v in verts]

        big_verts.extend(verts)
        big_edges.extend([[a + vert_count, b + vert_count] for a, b in edges])
        big_faces.extend([[j + vert_count for j in f] for f in faces])
        big_materials.extend(materials)

        vert_count += len(verts)

    if node.fixed_verts and len(sv_object.data.vertices) == len(big_verts):
        mesh = sv_object.data
        f_v = list(itertools.chain.from_iterable(big_verts))
        mesh.vertices.foreach_set('co', f_v)
        mesh.update()
    else:
        ''' get bmesh, write bmesh to obj, free bmesh'''
        bm = bmesh_from_pydata(big_verts,
                               big_edges,
                               big_faces,
                               normal_update=node.calc_normals)
        if materials:
            for face, material in zip(bm.faces[:], big_materials):
                if material is not None:
                    face.material_index = material
        bm.to_mesh(sv_object.data)
        bm.free()

    sv_object.hide_select = False
    sv_object.matrix_local = Matrix.Identity(4)
Beispiel #59
0
def get_vertex_normals(vecs, polygons):
    mesh = bmesh_from_pydata(vecs, [], polygons, normal_update=True)
    return [Vector(vert.normal) for vert in mesh.verts]
Beispiel #60
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not (any(
                self.outputs[name].is_linked
                for name in ['Vertices', 'Edges', 'Polygons', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]])
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        offsets_s = self.inputs['Offset'].sv_get()[0]
        segments_s = self.inputs['Segments'].sv_get()[0]
        profiles_s = self.inputs['Profile'].sv_get()[0]
        bevel_edges_s = self.inputs['BevelEdges'].sv_get(default=[[]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_bevel_faces = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, bevel_edges_s, offsets_s, segments_s,
            profiles_s
        ])

        for vertices, edges, faces, bevel_edges, offset, segments, profile in zip(
                *meshes):

            bm = bmesh_from_pydata(vertices, edges, faces)

            if bevel_edges:
                b_edges = []
                for edge in bevel_edges:
                    b_edge = [
                        e for e in bm.edges
                        if set([v.index for v in e.verts]) == set(edge)
                    ]
                    b_edges.append(b_edge[0])
            else:
                b_edges = bm.edges

            geom = list(bm.verts) + list(b_edges) + list(bm.faces)
            bevel_faces = bmesh.ops.bevel(
                bm,
                geom=geom,
                offset=offset,
                offset_type=int(self.offsetType),
                segments=segments,
                profile=profile,
                vertex_only=self.vertexOnly,
                #clamp_overlap=self.clampOverlap,
                material=-1)['faces']
            new_bevel_faces = [[v.index for v in face.verts]
                               for face in bevel_faces]
            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_bevel_faces.append(new_bevel_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['NewPolys'].is_linked:
            self.outputs['NewPolys'].sv_set(result_bevel_faces)