예제 #1
0
def emit_pointcloud(app, options, pointloud_name, usd_tfm, visibility,
                    usd_prim, xsi_parent):
    imp.reload(utils)
    usd_points = UsdGeom.Points(usd_prim)
    xsi_points = app.GetPrim("PointCloud", pointloud_name, xsi_parent)
    utils.set_xsi_transform(app, xsi_points, usd_tfm)
    utils.set_xsi_visibility(xsi_points, visibility)

    tree = create_usd_load_tree(app, xsi_points.ActivePrimitive.Geometry)

    if not utils.is_animated_points(usd_points):
        points_data = {}
        read_points_data(points_data, usd_points=usd_points)
        xsi_geometry = xsi_points.ActivePrimitive.Geometry
        set_pointcloud_from_data(app, xsi_geometry, points_data,
                                 options["XSIMath"])
    else:
        operator = app.AddCustomOp("USDPointsOperator",
                                   xsi_points.ActivePrimitive, "",
                                   "USDPointsOperator")
        operator.Parameters("file_path").Value = options["file_path"]
        operator.Parameters("points_path").Value = str(usd_prim.GetPath())
        operator.AlwaysEvaluate = True

        # swap ICE-tree and operator (ICE-tree should be at the top)
        app.MoveOperatorAfter(xsi_points.ActivePrimitive, tree, operator)

    return xsi_points
예제 #2
0
    def test_ComputePointCount(self):
        stage = Usd.Stage.Open('points.usda')
        unset = UsdGeom.Points.Get(stage, '/UnsetPoints')
        blocked = UsdGeom.Points.Get(stage, '/BlockedPoints')
        empty = UsdGeom.Points.Get(stage, '/EmptyPoints')
        timeSampled = UsdGeom.Points.Get(stage, '/TimeSampledPoints')
        timeSampledAndDefault = UsdGeom.Points.Get(
            stage, '/TimeSampledAndDefaultPoints')

        testTimeSamples = [(unset, Usd.TimeCode.EarliestTime(), 0),
                           (blocked, Usd.TimeCode.EarliestTime(), 0),
                           (empty, Usd.TimeCode.EarliestTime(), 0),
                           (timeSampled, Usd.TimeCode.EarliestTime(), 3),
                           (timeSampledAndDefault, Usd.TimeCode.EarliestTime(),
                            5)]
        testDefaults = [(unset, 0), (blocked, 0), (empty, 0), (timeSampled, 0),
                        (timeSampledAndDefault, 4)]

        for (schema, timeCode, expected) in testTimeSamples:
            self.assertTrue(schema)
            self.assertEqual(schema.GetPointCount(timeCode), expected)
        for (schema, expected) in testDefaults:
            self.assertTrue(schema)
            self.assertEqual(schema.GetPointCount(), expected)

        invalid = UsdGeom.Points(Usd.Prim())
        self.assertFalse(invalid)
        with self.assertRaises(RuntimeError):
            self.assertEqual(invalid.GetPointCount(), 0)
        with self.assertRaises(RuntimeError):
            self.assertEqual(
                invalid.GetPointCount(Usd.TimeCode.EarliestTime()), 0)
예제 #3
0
def read_points_data(data_dict,
                     file_path=None,
                     points_path=None,
                     usd_points=None):
    if usd_points is None:
        stage = Usd.Stage.Open(file_path)
        usd_points = UsdGeom.Points(stage.GetPrimAtPath(points_path))
    data_dict["points"] = read_points(usd_points)
    data_dict["widths"] = read_widths(usd_points)
예제 #4
0
파일: usd.py 프로젝트: n1ckfg/kaolin
def add_pointcloud(stage, points, scene_path, colors=None, time=None):
    r"""Add a pointcloud to an existing USD stage.

    Create a pointcloud represented by point instances of a sphere centered at each point coordinate.
    The stage is modified but not saved to disk.

    Args:
        stage (Usd.Stage): Stage onto which to add the pointcloud.
        points (torch.FloatTensor): Pointcloud tensor containing ``N`` points of shape ``(N, 3)``.
        scene_path (str): Absolute path of pointcloud within the USD file scene. Must be a valid Sdf.Path.
        colors (torch.FloatTensor, optional): Color tensor corresponding each point in the pointcloud
            tensor of shape ``(N, 3)``.
        time (int, optional): Positive integer defining the time at which the supplied parameters correspond to.
    Returns:
        (Usd.Stage)

    Example:
        >>> stage = create_stage('./new_stage.usd')
        >>> points = torch.rand(100, 3)
        >>> stage = add_pointcloud(stage, points, '/World/PointClouds/pointcloud_0')
        >>> stage.Save()
    """
    scene_path = Sdf.Path(scene_path)
    if time is None:
        time = Usd.TimeCode.Default()

    if stage.GetPrimAtPath(scene_path):
        points_prim = stage.GetPrimAtPath(scene_path)
    else:
        points_prim = stage.DefinePrim(scene_path, 'Points')
    geom_points = UsdGeom.Points(points_prim)

    # Calculate default point scale
    bounds = points.max(dim=0)[0] - points.min(dim=0)[0]
    min_bound = min(bounds)
    scale = (min_bound / points.size(0) ** (1 / 3)).item()

    # Generate instancer parameters
    positions = points.cpu().tolist()
    scales = [scale, ] * points.size(0)

    # Populate UsdGeomPoints
    geom_points.GetPointsAttr().Set(points.numpy(), time=time)
    geom_points.GetWidthsAttr().Set(Vt.FloatArray(scales), time=time)

    if colors is not None:
        assert colors.shape == points.shape, "Colors and points must have the same shape."
        geom_points.GetDisplayColorAttr().Set(colors.numpy(), time=time)

    return stage
예제 #5
0
파일: usd.py 프로젝트: n1ckfg/kaolin
def get_pointcloud_bracketing_time_samples(stage, scene_path, target_time):
    """Returns two time samples that bracket target_time for point cloud attributes at a specified
    scene_path.

    Args:
        stage (Usd.Stage)
        scene_path (str)
        target_time (Number)
    Returns:
        (iterable of 2 numbers)
    """
    # Note: can also get usd_attr.GetTimeSamples()
    prim = stage.GetPrimAtPath(scene_path)

    if UsdGeom.Points(prim):
        geom_points = UsdGeom.Points(prim)
        result = geom_points.GetPointsAttr().GetBracketingTimeSamples(target_time)
    elif UsdGeom.PointInstancer(prim):
        instancer = UsdGeom.PointInstancer(prim)
        result = instancer.GetPositionsAttr().GetBracketingTimeSamples(target_time)
    else:
        raise TypeError("The prim is neither UsdGeomPoints nor UsdGeomPointInstancer.")
    return result
예제 #6
0
def emit_pointcloud(app,
                    options,
                    pointloud_name,
                    usd_tfm,
                    visibility,
                    usd_prim,
                    is_strands,
                    xsi_parent,
                    is_simple=False):
    '''if is_simple is True, then we should ignore in-object ransform
    '''
    if DEBUG_MODE:
        imp.reload(materials)
        imp.reload(utils)

    usd_object = UsdGeom.BasisCurves(
        usd_prim) if is_strands else UsdGeom.Points(usd_prim)
    xsi_points = app.GetPrim("PointCloud", pointloud_name, xsi_parent)

    if options.get("is_materials", False):
        usd_material = UsdShade.MaterialBindingAPI(
            usd_prim).GetDirectBinding().GetMaterial()
        xsi_material = materials.import_material(
            app, usd_material, library_name=options["file_name"])
        if xsi_material is not None:
            app.AssignMaterial(xsi_material.FullName + "," +
                               xsi_points.FullName)

    utils.set_xsi_transform(app,
                            xsi_points,
                            usd_tfm,
                            up_key=options["up_axis"])
    utils.set_xsi_visibility(xsi_points, visibility)
    if "project_path" in options:
        is_constant = write_ice_cache(usd_object, is_strands, xsi_points,
                                      options["project_path"],
                                      options["file_name"], options["up_axis"],
                                      is_simple)
        # build ice-tree with caching node
        build_ice_tree(app, xsi_points, is_constant, options["file_name"])

    return xsi_points
예제 #7
0
    def test_Points(self):
        stage = Usd.Stage.Open("testPoints.usda")

        points = UsdGeom.Points(stage.GetPrimAtPath("/Points"))

        # Verify the extent computation when no transform matrix is given.
        self.verifyExtent(points, [(-0.5, -0.5, -0.5), (3.25, 2.0, 2.25)])

        # Verify the extent computation when no transform matrix is given.
        self.verifyExtent(points, [(-0.5, -0.5, -0.5), (3.25, 2.0, 2.25)],
                          Gf.Matrix4d(1.0))

        # Apply an arbitrary transform matrix. Note that this is different from
        # the extent displayed in Usdview. If you open testPoints.usda and
        # select /StrangePoints, you will see the box is larger than it needs to
        # be (it transforms the bounding box around the points, not the points
        # themselves like ComputeExtentFromPlugins). If you select
        # /StrangePointsComputedExtent, it will display the (much tighter)
        # computed extent used below.
        self.verifyExtent(
            points,
            [(0.18938279151916504, 1.189382791519165, 1.0946913957595825),
             (4.8312811851501465, 3.609475612640381, 2.041466236114502)],
            STRANGE_TRANSFORM)
예제 #8
0
파일: usd.py 프로젝트: n1ckfg/kaolin
def import_pointclouds(file_path, scene_paths=None, times=None):
    r"""Import one or more pointclouds from a USD file.

    Assumes that pointclouds are interpreted using point instancers or UsdGeomPoints. Converts the coordinates
    of each point instance to a point within the output pointcloud.

    Args:
        file_path (str): Path to usd file (\*.usd, \*.usda).
        scene_paths (list of str, optional): Scene path(s) within the USD file indicating which primitive(s)
            to import. If None, will return all pointclouds found based on PointInstancer or UsdGeomPoints prims with `kaolin_type`
            primvar set to `PointCloud`.
        times (list of int): Positive integers indicating the time at which to retrieve parameters.
    Returns:
        list of namedtuple of:
            - **points** (list of torch.FloatTensor): of shape (num_points, 3)
            - **colors** (list of torch.FloatTensor): of shape (num_points, 3)
            - **normals** (list of torch.FloatTensor): of shape (num_points, 2)

    Example:
        >>> points = torch.rand(100, 3)
        >>> stage = export_pointclouds('./new_stage.usd', [points, points, points])
        >>> pointclouds = import_pointclouds(file_path='./new_stage.usd')[0]
        >>> len(pointclouds)
        3
        >>> pointclouds[0].shape
        torch.Size([100, 3])
    """
    assert os.path.exists(file_path)

    if scene_paths is None:
        scene_paths = get_pointcloud_scene_paths(file_path)
    if times is None:
        times = [Usd.TimeCode.Default()] * len(scene_paths)

    pointclouds = []
    colors = []
    normals = []
    stage = Usd.Stage.Open(file_path)
    for scene_path, time in zip(scene_paths, times):
        prim = stage.GetPrimAtPath(scene_path)
        assert prim, f'The prim at {scene_path} does not exist.'

        if UsdGeom.Points(prim):
            geom_points = UsdGeom.Points(prim)
            pointclouds.append(torch.tensor(geom_points.GetPointsAttr().Get(time=time)))

            color = geom_points.GetDisplayColorAttr().Get(time=time)

            if color is None:
                colors.append(color)
            else:
                colors.append(torch.tensor(color))
        elif UsdGeom.PointInstancer(prim):
            instancer = UsdGeom.PointInstancer(prim)
            pointclouds.append(torch.tensor(instancer.GetPositionsAttr().Get(time=time)))
            colors.append(None)
        else:
            raise TypeError("The prim is neither UsdGeomPoints nor UsdGeomPointInstancer.")

    # TODO: place holders for normals for now
    normals = [None] * len(colors)

    params = [pointclouds, colors, normals]
    return [pointcloud_return_type(p, c, n) for p, c, n in zip(*params)]