Beispiel #1
0
class Point(GeometryNode):
    __identifier__ = 'OpenGL'
    NODE_NAME = 'Point'

    def __init__(self):
        super(Point, self).__init__()
        self.create_property("Color", (1.0, 1.0, 1.0),
                             widget_type=NODE_PROP_COLORPICKER)
        self.create_property("Size", 0.1, widget_type=NODE_PROP_FLOAT)
        self.create_property("Pos", [0.0, 0.0, 0.0],
                             widget_type=NODE_PROP_VECTOR3)
        self.cook()

    def run(self):
        self.geo = Mesh()
        self.geo.addVertex(self.get_property("Pos"))
        self.geo.createAttribute('vertex',
                                 'color',
                                 'vector3', [1, 1, 1],
                                 applyValue=True)
        self.geo.setVertexAttrib("color", 0, list(self.get_property("Color")))
        self.geo.createAttribute('vertex',
                                 'pscale',
                                 'float',
                                 1.0,
                                 applyValue=True)
        self.geo.setVertexAttrib("pscale", 0, self.get_property("Size"))
Beispiel #2
0
class Arrow(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Arrow'

    def __init__(self):
        super(Arrow, self).__init__()
        params = [{'name': 'Radius', 'type': 'vector2', 'value': [1, 1.5]},
                  {'name': 'Height', 'type': 'vector2', 'value': [2, 4]},
                  {'name': 'Cylinder split', 'type': 'int', 'value': 1, 'limits': (1, 10)},
                  {'name': 'Cone split', 'type': 'int', 'value': 1, 'limits': (1, 10)},
                  {'name': 'Resolution', 'type': 'int', 'value': 20, 'limits': (3, 30)}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        radius = self.get_property("Radius")
        height = self.get_property("Height")

        tri = o3d.geometry.TriangleMesh.create_arrow(radius[0], radius[1], height[0], height[1],
                                                     self.get_property("Resolution"),
                                                     self.get_property("Cylinder split"),
                                                     self.get_property("Cone split"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #3
0
    def run(self):
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumFaces() == 0 or geo.getNumVertexes() == 0:
            return
        count = self.get_property('Count')
        method = self.get_property('Method')
        iteration = self.get_property('Relax Iteration')

        tri = geo.getTriangulateMesh()
        mesh = o3d.geometry.TriangleMesh()
        mesh.vertices = o3d.utility.Vector3dVector(tri.points())
        mesh.triangles = o3d.utility.Vector3iVector(tri.face_vertex_indices())

        pcd = None
        if method == 'Uniform':
            pcd = mesh.sample_points_uniformly(count)
        elif method == 'Relax':
            pcd = mesh.sample_points_poisson_disk(count, iteration)

        self.geo = Mesh()
        self.geo.addVertices(np.array(pcd.points))
        mesh.clear()
Beispiel #4
0
class Torus(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Torus'

    def __init__(self):
        super(Torus, self).__init__()
        params = [{'name': 'Radius', 'type': 'vector2', 'value': [1, 0.5]},
                  {'name': 'Radial resolution', 'type': 'int', 'value': 20, 'limits': (3, 50)},
                  {'name': 'Tubular resolution', 'type': 'int', 'value': 20, 'limits': (3, 50)}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        rad = self.get_property("Radius")
        if rad[0] == 0:
            rad[0] = 0.0001
        if rad[1] == 0:
            rad[1] = 0.0001

        r1 = self.get_property("Radial resolution")
        r2 = self.get_property("Tubular resolution")
        if r1 < 3 or r2 < 3:
            self.geo = None
            return
        faces, vertices = generate_torus(rad[0], rad[1], r1, r2)
        self.geo = Mesh()
        self.geo.addVertices(vertices)
        self.geo.addFaces(faces)
Beispiel #5
0
    def run(self):
        self.geo = None
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumVertexes() == 0:
            return

        pts = [Point_3(*i) for i in geo.getVertexes()]

        res = Polyhedron_3()
        CGAL_Convex_hull_3.convex_hull_3(pts, res)
        pts = {}
        [pts.update({v: idx}) for idx, v in enumerate(res.vertices())]

        ff = []
        for f in res.facets():
            he = f.halfedge()
            done = he
            faces = []
            while True:
                faces.append(pts[he.vertex()])
                he = he.next()
                if he == done:
                    break

            ff.append(faces)

        self.geo = Mesh()
        self.geo.addVertices([[i.x(), i.y(), i.z()] for i in res.points()])
        self.geo.addFaces(ff)
Beispiel #6
0
class Face(GeometryNode):
    __identifier__ = 'OpenGL'
    NODE_NAME = 'Face'

    def __init__(self):
        super(Face, self).__init__()
        self.add_input("Points", multi_input=True)

    def run(self):
        self.geo = Mesh()
        geos = [
            port.node().get_data(port)
            for port in self.get_port(0).connected_ports()
        ]
        points = []
        pscales = []
        colors = []
        for geo in geos:
            points.append(geo.getVertexAttrib('pos', 0))
            pscales.append(geo.getVertexAttrib('pscale', 0))
            colors.append(geo.getVertexAttrib('color', 0))
        self.geo.addVertices(points)
        self.geo.setVertexAttribData('color',
                                     colors,
                                     attribType='vector3',
                                     defaultValue=[1, 1, 1])
        self.geo.setVertexAttribData('pscale',
                                     pscales,
                                     attribType='float',
                                     defaultValue=1.0)
        if self.geo.getNumVertexes() > 2:
            self.geo.addFace(list(range(self.geo.getNumVertexes())))
Beispiel #7
0
    def run(self):
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumFaces() == 0 or geo.getNumVertexes() == 0:
            return
        itera = self.get_property("Iteration")
        if itera == 0:
            return

        mesh = geo.getTriangulateMesh()
        v = mesh.points()
        f = mesh.face_vertex_indices()

        mt = self.get_property("Method")
        if mt == "Upsample":
            for i in range(itera):
                v, f = igl.upsample(v, f)
        elif mt == "Loop":
            for i in range(itera):
                v, f = igl.loop(v, f)

        self.geo = Mesh()
        self.geo.addVertices(v)
        self.geo.addFaces(f)
Beispiel #8
0
class Moebius(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Moebius'

    def __init__(self):
        super(Moebius, self).__init__()
        params = [{'name': 'Length Split', 'type': 'int', 'value': 70, 'limits': (1, 100)},
                  {'name': 'Width Split', 'type': 'int', 'value': 15, 'limits': (1, 100)},
                  {'name': 'Twists', 'type': 'int', 'value': 1, 'limits': (0, 10)},
                  {'name': 'Raidus', 'type': 'float', 'value': 1, 'limits': (0, 10)},
                  {'name': 'Flatness', 'type': 'float', 'value': 1, 'limits': (0, 30)},
                  {'name': 'Width', 'type': 'float', 'value': 1, 'limits': (0, 10)},
                  {'name': 'Scale', 'type': 'float', 'value': 1, 'limits': (0, 30)}]

        self.set_parameters(params)

        self.cook()

    def run(self):
        tri = o3d.geometry.TriangleMesh.create_moebius(self.get_property('Length Split'),
                                                       self.get_property('Width Split'),
                                                       self.get_property("Twists"),
                                                       self.get_property("Raidus"),
                                                       self.get_property("Flatness"),
                                                       self.get_property("Width"),
                                                       self.get_property("Scale"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #9
0
    def load(self, filePath):
        self.geo = Mesh()
        scene = pyassimp.load(filePath, processing=import_flags)
        norms = None
        uvs = None
        for mesh in scene.meshes:
            offset = self.geo.getNumVertexes()
            self.geo.addVertices(mesh.vertices)
            for vts in mesh.faces:
                self.geo.mesh.add_face([self.geo.mesh.vertex_handle(i + offset) for i in vts if i >= 0])
            normals = mesh.normals
            if normals.shape[0] > 0:
                if norms is None:
                    norms = [normals]
                else:
                    norms.append(normals)
            elif norms is not None:
                norms.append(np.zeros((len(mesh.vertices), 3)))

            texcoords = mesh.texturecoords
            if texcoords.shape[0] > 0:
                if uvs is None:
                    uvs = [texcoords[0]]
                else:
                    uvs.append(texcoords[0])
            elif uvs is not None:
                uvs.append(np.zeros((len(mesh.vertices), 3)))

        if norms is not None:
            self.geo.setVertexAttribData('normal', np.vstack(norms), attribType='vector3', defaultValue=[0, 0, 0])
        if uvs is not None:
            self.geo.setVertexAttribData('uv', np.vstack(uvs), attribType='vector3', defaultValue=[0, 0, 0])

        pyassimp.release(scene)
Beispiel #10
0
class Tube(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Tube'

    def __init__(self):
        super(Tube, self).__init__()
        params = [{'name': 'Bottom center', 'type': 'vector3', 'value': [0, 0, 0]},
                  {'name': 'Top center', 'type': 'vector3', 'value': [0, 1, 0]},
                  {'name': 'Outer radius', 'type': 'vector2', 'value': [0.5, 0.5]},
                  {'name': 'Inner radius', 'type': 'vector2', 'value': [0.3, 0.3]},
                  {'name': 'Segments', 'type': 'int', 'value': 10, 'limits': (3, 30)},
                  {'name': 'Quad', 'type': 'bool', 'value': True}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        outer = self.get_property("Outer radius")
        inner = self.get_property("Inner radius")
        s = self.get_property("Segments")
        if s < 3:
            self.geo = None
            return
        vertices, faces = generate_tube(self.get_property("Bottom center"), self.get_property("Top center"),
                                        outer[0], outer[1], inner[0], inner[1], s,
                                        self.get_property("Quad"))
        self.geo = Mesh()
        self.geo.addVertices(vertices)
        self.geo.addFaces(faces)
Beispiel #11
0
    def run(self):
        size = self.get_property("Size")
        if size == 0:
            size = 0.0001
        tri = o3d.geometry.TriangleMesh.create_coordinate_frame(size, self.get_property("Origin"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #12
0
    def run(self):
        rad = self.get_property("Radius")
        if rad == 0:
            rad = 0.0001

        tri = o3d.geometry.TriangleMesh.create_tetrahedron(rad)

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #13
0
    def run(self):
        radius = self.get_property("Radius")
        height = self.get_property("Height")

        tri = o3d.geometry.TriangleMesh.create_arrow(radius[0], radius[1], height[0], height[1],
                                                     self.get_property("Resolution"),
                                                     self.get_property("Cylinder split"),
                                                     self.get_property("Cone split"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #14
0
    def run(self):
        tri = o3d.geometry.TriangleMesh.create_moebius(self.get_property('Length Split'),
                                                       self.get_property('Width Split'),
                                                       self.get_property("Twists"),
                                                       self.get_property("Raidus"),
                                                       self.get_property("Flatness"),
                                                       self.get_property("Width"),
                                                       self.get_property("Scale"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #15
0
 def run(self):
     outer = self.get_property("Outer radius")
     inner = self.get_property("Inner radius")
     s = self.get_property("Segments")
     if s < 3:
         self.geo = None
         return
     vertices, faces = generate_tube(self.get_property("Bottom center"), self.get_property("Top center"),
                                     outer[0], outer[1], inner[0], inner[1], s,
                                     self.get_property("Quad"))
     self.geo = Mesh()
     self.geo.addVertices(vertices)
     self.geo.addFaces(faces)
Beispiel #16
0
class Cylinder(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Cylinder'

    def __init__(self):
        super(Cylinder, self).__init__()
        params = [{'name': 'Radius', 'type': 'float', 'value': 1.0},
                  {'name': 'Height', 'type': 'float', 'value': 2.0},
                  {'name': 'Split', 'type': 'int', 'value': 4, 'limits': (1, 10)},
                  {'name': 'Resolution', 'type': 'int', 'value': 20, 'limits': (3, 30)},
                  {'name': 'Cap', 'type': 'bool', 'value': True}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        s = self.get_property("Resolution")
        if s < 3:
            self.geo = None
            return

        tri, quad, vt = generate_cylinder(self.get_property("Radius"),
                                          self.get_property("Height"),
                                          s,
                                          self.get_property("Split"))

        self.geo = Mesh()
        self.geo.addVertices(vt)
        self.geo.addFaces(quad)
        if self.get_property("Cap"):
            self.geo.addFaces(tri)
        else:
            self.geo.removeVertices([0, 1])
Beispiel #17
0
 def run(self):
     self.geo = Mesh()
     self.geo.addVertex(self.get_property("Pos"))
     self.geo.createAttribute('vertex',
                              'color',
                              'vector3', [1, 1, 1],
                              applyValue=True)
     self.geo.setVertexAttrib("color", 0, list(self.get_property("Color")))
     self.geo.createAttribute('vertex',
                              'pscale',
                              'float',
                              1.0,
                              applyValue=True)
     self.geo.setVertexAttrib("pscale", 0, self.get_property("Size"))
Beispiel #18
0
    def run(self):
        rad = self.get_property("Radius")
        if rad == 0:
            rad = 0.0001

        s = self.get_property("Resolution")
        if s < 2:
            self.geo = None
            return

        tri, quad, vt = generate_sphere(rad, s)
        self.geo = Mesh()
        self.geo.addVertices(vt)
        self.geo.addFaces(tri)
        self.geo.addFaces(quad)
Beispiel #19
0
    def run(self):
        rad = self.get_property("Radius")
        if rad[0] == 0:
            rad[0] = 0.0001
        if rad[1] == 0:
            rad[1] = 0.0001

        r1 = self.get_property("Radial resolution")
        r2 = self.get_property("Tubular resolution")
        if r1 < 3 or r2 < 3:
            self.geo = None
            return
        faces, vertices = generate_torus(rad[0], rad[1], r1, r2)
        self.geo = Mesh()
        self.geo.addVertices(vertices)
        self.geo.addFaces(faces)
Beispiel #20
0
    def run(self):
        s = self.get_property("Resolution")
        if s < 3:
            self.geo = None
            return

        tri, quad, vt = generate_cone(self.get_property("Radius"),
                                      self.get_property("Height"),
                                      s,
                                      self.get_property("Split"))

        self.geo = Mesh()
        self.geo.addVertices(vt)
        self.geo.addFaces(quad)
        self.geo.addFaces(tri)
        if not self.get_property("Cap"):
            self.geo.removeVertex(0, True)
Beispiel #21
0
    def run(self):
        s = self.get_property("Resolution")
        if s < 3:
            self.geo = None
            return

        tri, quad, vt = generate_cylinder(self.get_property("Radius"),
                                          self.get_property("Height"),
                                          s,
                                          self.get_property("Split"))

        self.geo = Mesh()
        self.geo.addVertices(vt)
        self.geo.addFaces(quad)
        if self.get_property("Cap"):
            self.geo.addFaces(tri)
        else:
            self.geo.removeVertices([0, 1])
Beispiel #22
0
class Tetrahedron(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Tetrahedron'

    def __init__(self):
        super(Tetrahedron, self).__init__()
        params = [{'name': 'Radius', 'type': 'float', 'value': 1.0}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        rad = self.get_property("Radius")
        if rad == 0:
            rad = 0.0001

        tri = o3d.geometry.TriangleMesh.create_tetrahedron(rad)

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #23
0
class CoordinateFrame(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Coordinate Frame'

    def __init__(self):
        super(CoordinateFrame, self).__init__()
        params = [{'name': 'Size', 'type': 'float', 'value': 1.0},
                  {'name': 'Origin', 'type': 'vector3', 'value': [0, 0, 0]}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        size = self.get_property("Size")
        if size == 0:
            size = 0.0001
        tri = o3d.geometry.TriangleMesh.create_coordinate_frame(size, self.get_property("Origin"))

        self.geo = Mesh()
        self.geo.addVertices(np.array(tri.vertices)[:, [0, 2, 1]])
        self.geo.addFaces(np.array(tri.triangles))
Beispiel #24
0
class Sphere(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Sphere'

    def __init__(self):
        super(Sphere, self).__init__()
        params = [{'name': 'Radius', 'type': 'float', 'value': 1.0},
                  {'name': 'Resolution', 'type': 'int', 'value': 20, 'limits': (2, 50)}]
        self.set_parameters(params)

        self.cook()

    def run(self):
        rad = self.get_property("Radius")
        if rad == 0:
            rad = 0.0001

        s = self.get_property("Resolution")
        if s < 2:
            self.geo = None
            return

        tri, quad, vt = generate_sphere(rad, s)
        self.geo = Mesh()
        self.geo.addVertices(vt)
        self.geo.addFaces(tri)
        self.geo.addFaces(quad)
Beispiel #25
0
class ConvexHull(GeometryNode):
    __identifier__ = 'Utility'
    NODE_NAME = 'ConvexHull'

    def __init__(self):
        super(ConvexHull, self).__init__()
        self.add_input("geo")

    def run(self):
        self.geo = None
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumVertexes() == 0:
            return

        pts = [Point_3(*i) for i in geo.getVertexes()]

        res = Polyhedron_3()
        CGAL_Convex_hull_3.convex_hull_3(pts, res)
        pts = {}
        [pts.update({v: idx}) for idx, v in enumerate(res.vertices())]

        ff = []
        for f in res.facets():
            he = f.halfedge()
            done = he
            faces = []
            while True:
                faces.append(pts[he.vertex()])
                he = he.next()
                if he == done:
                    break

            ff.append(faces)

        self.geo = Mesh()
        self.geo.addVertices([[i.x(), i.y(), i.z()] for i in res.points()])
        self.geo.addFaces(ff)
Beispiel #26
0
class Grid(GeometryNode):
    __identifier__ = 'Primitives'
    NODE_NAME = 'Grid'

    def __init__(self):
        super(Grid, self).__init__()
        params = [{'name': 'Size', 'type': 'vector2', 'value': [10, 10]},
                  {'name': 'Resolution', 'type': 'vector2i', 'value': [10, 10]}]
        self.set_parameters(params)
        self.cook()

    def run(self):
        size = self.get_property("Size")
        resolution = self.get_property("Resolution")
        x = size[0] * 0.5
        z = size[1] * 0.5
        fx = resolution[0]
        fz = resolution[1]

        if fx < 2 or fz < 2:
            self.geo = None
            return

        x_range = np.linspace(-x, x, fx)
        z_range = np.linspace(-z, z, fz)
        vertices = np.dstack(np.meshgrid(x_range, z_range, np.array([0.0]))).reshape(-1, 3)
        a = np.add.outer(np.array(range(fx - 1)), fx * np.array(range(fz - 1)))
        faces = np.dstack([a, a + 1, a + fx + 1, a + fx]).reshape(-1, 4)

        nms = np.zeros((vertices.shape[0], 3), dtype=float)
        nms[..., 1] = 1
        self.geo = Mesh()
        self.geo.addVertices(vertices[:, [0, 2, 1]])
        self.geo.addFaces(faces)
        self.geo.setVertexAttribData('normal', nms, attribType='vector3', defaultValue=[0, 0, 0])
Beispiel #27
0
    def run(self):
        size = self.get_property("Size")
        x = size[0] * 0.5
        y = size[1] * 0.5
        z = size[2] * 0.5
        self.geo = Mesh()
        v1 = self.geo.addVertex([x, -y, -z])
        v2 = self.geo.addVertex([x, -y, z])
        v3 = self.geo.addVertex([x, y, z])
        v4 = self.geo.addVertex([x, y, -z])
        v5 = self.geo.addVertex([-x, -y, -z])
        v6 = self.geo.addVertex([-x, -y, z])
        v7 = self.geo.addVertex([-x, y, z])
        v8 = self.geo.addVertex([-x, y, -z])

        self.geo.addFace([v1, v2, v3, v4])
        self.geo.addFace([v2, v6, v7, v3])
        self.geo.addFace([v6, v5, v8, v7])
        self.geo.addFace([v5, v1, v4, v8])
        self.geo.addFace([v4, v3, v7, v8])
        self.geo.addFace([v5, v6, v2, v1])
        self.geo.mesh.update_normals()
Beispiel #28
0
 def run(self):
     self.geo = Mesh()
     geos = [
         port.node().get_data(port)
         for port in self.get_port(0).connected_ports()
     ]
     points = []
     pscales = []
     colors = []
     for geo in geos:
         points.append(geo.getVertexAttrib('pos', 0))
         pscales.append(geo.getVertexAttrib('pscale', 0))
         colors.append(geo.getVertexAttrib('color', 0))
     self.geo.addVertices(points)
     self.geo.setVertexAttribData('color',
                                  colors,
                                  attribType='vector3',
                                  defaultValue=[1, 1, 1])
     self.geo.setVertexAttribData('pscale',
                                  pscales,
                                  attribType='float',
                                  defaultValue=1.0)
     if self.geo.getNumVertexes() > 2:
         self.geo.addFace(list(range(self.geo.getNumVertexes())))
Beispiel #29
0
class Scatter(GeometryNode):
    __identifier__ = 'Geometry'
    NODE_NAME = 'Scatter'

    def __init__(self):
        super(Scatter, self).__init__()
        self.add_combo_menu("Method", "Method", items=['Uniform', "Relax"])
        self.add_int_input("Count", "Count", 100, range=(0, 1000))
        self.add_int_input("Relax Iteration", "Relax Iteration", 5, range=(1, 10))
        self.add_input("geo")

    def run(self):
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumFaces() == 0 or geo.getNumVertexes() == 0:
            return
        count = self.get_property('Count')
        method = self.get_property('Method')
        iteration = self.get_property('Relax Iteration')

        tri = geo.getTriangulateMesh()
        mesh = o3d.geometry.TriangleMesh()
        mesh.vertices = o3d.utility.Vector3dVector(tri.points())
        mesh.triangles = o3d.utility.Vector3iVector(tri.face_vertex_indices())

        pcd = None
        if method == 'Uniform':
            pcd = mesh.sample_points_uniformly(count)
        elif method == 'Relax':
            pcd = mesh.sample_points_poisson_disk(count, iteration)

        self.geo = Mesh()
        self.geo.addVertices(np.array(pcd.points))
        mesh.clear()
Beispiel #30
0
class Subdivide(GeometryNode):
    __identifier__ = 'Geometry'
    NODE_NAME = 'Subdivide'

    def __init__(self):
        super(Subdivide, self).__init__()
        self.add_combo_menu("Method", "Method", items=["Upsample", "Loop"])
        self.add_int_input("Iteration", "Iteration", 1, range=(0, 10))
        self.add_input("geo")

    def run(self):
        geo = self.get_input_geometry_ref(0)
        if geo is None:
            return

        if geo.getNumFaces() == 0 or geo.getNumVertexes() == 0:
            return
        itera = self.get_property("Iteration")
        if itera == 0:
            return

        mesh = geo.getTriangulateMesh()
        v = mesh.points()
        f = mesh.face_vertex_indices()

        mt = self.get_property("Method")
        if mt == "Upsample":
            for i in range(itera):
                v, f = igl.upsample(v, f)
        elif mt == "Loop":
            for i in range(itera):
                v, f = igl.loop(v, f)

        self.geo = Mesh()
        self.geo.addVertices(v)
        self.geo.addFaces(f)