def encodeMesh(self, stage, mesh, fileName): """Compresses mesh to file and strips geometry properties from USD mesh.""" # Prepare options for Draco encoder. preserve_polygons = self.fromBool(self.options.preserve_polygons, False) preserve_pos_order = self.fromBool(self.options.discard_subdivision, True) preserve_holes = self.fromBool(self.options.discard_subdivision, True) # Compress mesh geometry with Draco and write it to file. success = UsdDraco._WriteDraco(mesh, fileName, self.options.qp, self.options.qt, self.options.qn, self.options.cl, preserve_polygons, preserve_pos_order, preserve_holes) if not success: sys.exit('Could not encode mesh: ' + str(mesh.GetPrim().GetPrimPath())) # Strip encoded geometry properties from the USD mesh. for name in self.ENCODED_PROPERTIES: self.removePropertyOrExit(stage, mesh, name) # Strip encoded geometry primvars from the USD mesh. for primvar in UsdGeom.PrimvarsAPI(mesh.GetPrim()).GetPrimvars(): if UsdDraco._PrimvarSupported(primvar): name = primvar.GetName() self.removePropertyOrExit(stage, mesh, name) self.removePropertyOrExit(stage, mesh, name + ':indices') # Add Draco file as a reference to the USD mesh. mesh.GetPrim().GetReferences().AddReference(fileName)
def add_pointcloud(stage, points, scene_path, 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. 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): instancer_prim = stage.GetPrimAtPath(scene_path) else: instancer_prim = stage.DefinePrim(scene_path, 'PointInstancer') instancer = UsdGeom.PointInstancer(instancer_prim) assert instancer sphere = UsdGeom.Sphere.Define(stage, f'{scene_path}/sphere') sphere.GetRadiusAttr().Set(0.5) instancer.CreatePrototypesRel().SetTargets([sphere.GetPath()]) # 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 indices = [0] * points.size(0) positions = points.cpu().tolist() scales = [(scale, ) * 3] * points.size(0) # Populate point instancer instancer.GetProtoIndicesAttr().Set(indices, time=time) instancer.GetPositionsAttr().Set(positions, time=time) instancer.GetScalesAttr().Set(scales, time=time) # Create a primvar to identify the point instancer as a Kaolin PointCloud prim = stage.GetPrimAtPath(instancer.GetPath()) pv = UsdGeom.PrimvarsAPI(prim).CreatePrimvar('kaolin_type', Sdf.ValueTypeNames.String) pv.Set('PointCloud') return stage
def test_PrimvarIndicesBlock(self): # We'll put all our Primvar on a single mesh gprim stage = Usd.Stage.CreateInMemory('indexPrimvars.usda') gp = UsdGeom.Mesh.Define(stage, '/myMesh') gp_pv = UsdGeom.PrimvarsAPI(gp) foo = gp_pv.CreatePrimvar('foo', Sdf.ValueTypeNames.FloatArray) indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) self.assertTrue(foo.SetIndices(indices)) self.assertTrue(foo.IsIndexed()) self.assertTrue(foo.GetIndicesAttr()) foo.BlockIndices() self.assertFalse(foo.IsIndexed()) # The indices value is blocked, but the attribute continues to exist. self.assertTrue(foo.GetIndicesAttr())
def _convert_primitive_to_mesh(self, gltf_primitive, usd_node, gltf_node, gltf_mesh): """ Converts a glTF mesh primitive to a USD mesh Arguments: name {str} -- name of the primitive primitive {dict} -- glTF primitive usd_parent_node {str} -- USD parent xform node_index {int} -- glTF node index double_sided {bool} -- specifies if the primitive is double sided """ parent_node = usd_node parent_path = parent_node.GetPath() attributes = gltf_primitive.get_attributes() skel_root = None targets = gltf_primitive.get_morph_targets() if 'JOINTS_0' in attributes or len(targets) > 0: skeleton_path = '{0}/{1}'.format(usd_node.GetPath(), 'skeleton_root') skel_root = UsdSkel.Root.Define(self.stage, skeleton_path) parent_node = skel_root parent_path = parent_node.GetPath() mesh = UsdGeom.Mesh.Define( self.stage, '{0}/{1}'.format( parent_node.GetPath(), GLTF2USDUtils.convert_to_usd_friendly_node_name( gltf_primitive.get_name()))) mesh.CreateSubdivisionSchemeAttr().Set('none') material = gltf_primitive.get_material() if material != None: if material.is_double_sided(): mesh.CreateDoubleSidedAttr().Set(True) usd_material = self.usd_materials[material.get_index()] UsdShade.MaterialBindingAPI(mesh).Bind( usd_material.get_usd_material()) for attribute_name in attributes: attribute = attributes[attribute_name] if attribute_name == 'POSITION': override_prim = self.stage.OverridePrim(mesh.GetPath()) override_prim.CreateAttribute( 'extent', Sdf.ValueTypeNames.Float3Array).Set( [attribute.get_min_value(), attribute.get_max_value()]) mesh.CreatePointsAttr(attribute.get_data()) if attribute_name == 'NORMAL': mesh.CreateNormalsAttr(attribute.get_data()) if attribute_name == 'COLOR_0': prim_var = UsdGeom.PrimvarsAPI(mesh) data = attribute.get_data() if attribute.accessor_type == 'VEC4': print( 'Vertex color alpha currently not supported. Defaulting to vertex color without alpha.' ) data = [ Gf.Vec3f(entry[0:3]) for entry in attribute.get_data() ] colors = prim_var.CreatePrimvar('displayColor', Sdf.ValueTypeNames.Color3f, 'vertex').Set(data) if attribute_name == 'TEXCOORD_0': data = attribute.get_data() invert_uvs = [] for uv in data: new_uv = (uv[0], 1 - uv[1]) invert_uvs.append(new_uv) prim_var = UsdGeom.PrimvarsAPI(mesh) uv = prim_var.CreatePrimvar('primvars:st0', Sdf.ValueTypeNames.TexCoord2fArray, 'vertex') uv.Set(invert_uvs) if attribute_name == 'JOINTS_0': self._convert_skin_to_usd(gltf_node, gltf_primitive, parent_node, mesh) weights = gltf_mesh.get_weights() if targets: skinBinding = UsdSkel.BindingAPI.Apply(mesh.GetPrim()) skeleton = UsdSkel.Skeleton.Define(self.stage, '{0}/skel'.format(parent_path)) # Create an animation for this mesh to hold the blendshapes skelAnim = UsdSkel.Animation.Define( self.stage, '{0}/skel/anim'.format(parent_path)) # link the skeleton animation to skelAnim skinBinding.CreateAnimationSourceRel().AddTarget( skelAnim.GetPath()) # link the skeleton to skeleton skinBinding.CreateSkeletonRel().AddTarget(skeleton.GetPath()) # Set blendshape names on the animation names = [] for i, _ in enumerate(gltf_mesh.get_weights()): targets[i].get_name() blend_shape_name = GLTF2USDUtils.convert_to_usd_friendly_node_name( targets[i].get_name()) names.append(blend_shape_name) skelAnim.CreateBlendShapesAttr().Set(names) skinBinding.CreateBlendShapesAttr(names) # Set the starting weights of each blendshape to the weights defined in the glTF primitive skelAnim.CreateBlendShapeWeightsAttr().Set(weights) blend_shape_targets = skinBinding.CreateBlendShapeTargetsRel() # Define offsets for each blendshape, and add them as skel:blendShapes and skel:blendShapeTargets for i, name in enumerate(names): offsets = targets[i].get_attributes()['POSITION'] blend_shape_name = '{0}/{1}'.format(mesh.GetPath(), name) # define blendshapes in the mesh blend_shape = UsdSkel.BlendShape.Define( self.stage, blend_shape_name) blend_shape.CreateOffsetsAttr(offsets) blend_shape_targets.AddTarget(name) indices = gltf_primitive.get_indices() num_faces = len(indices) / 3 face_count = [3] * num_faces mesh.CreateFaceVertexCountsAttr(face_count) mesh.CreateFaceVertexIndicesAttr(indices)
def test_PrimvarInheritance(self): stage = Usd.Stage.CreateInMemory('primvarInheritance.usda') s0 = UsdGeom.Xform.Define(stage, '/s0') s1 = UsdGeom.Xform.Define(stage, '/s0/s1') s2 = UsdGeom.Xform.Define(stage, '/s0/s1/s2') s3 = UsdGeom.Xform.Define(stage, '/s0/s1/s2/s3') s4 = UsdGeom.Mesh.Define(stage, '/s0/s1/s2/s3/s4') s0p = UsdGeom.PrimvarsAPI(s0) s1p = UsdGeom.PrimvarsAPI(s1) s2p = UsdGeom.PrimvarsAPI(s2) s3p = UsdGeom.PrimvarsAPI(s3) s4p = UsdGeom.PrimvarsAPI(s4) u1 = s1p.CreatePrimvar('u1', Sdf.ValueTypeNames.Float) u1.SetInterpolation(UsdGeom.Tokens.constant) u1.Set(1) u2 = s2p.CreatePrimvar('u2', Sdf.ValueTypeNames.Float) u2.SetInterpolation(UsdGeom.Tokens.constant) u2.Set(2) u3 = s3p.CreatePrimvar('u3', Sdf.ValueTypeNames.Float) u3.SetInterpolation(UsdGeom.Tokens.constant) u3.Set(3) # u4 overrides u3 on prim s4. u4 = s4p.CreatePrimvar('u3', Sdf.ValueTypeNames.Float) u4.SetInterpolation(UsdGeom.Tokens.constant) # Before setting a value on u4, let's test the various # enumeration methods, since Mesh has 2 builtin primvars self.assertEqual(len(s4p.GetPrimvars()), 3) self.assertEqual(len(s4p.GetAuthoredPrimvars()), 1) self.assertEqual(len(s4p.GetPrimvarsWithValues()), 0) self.assertEqual(len(s4p.GetPrimvarsWithAuthoredValues()), 0) # now set value, and retest u4.Set(4) self.assertEqual(len(s4p.GetPrimvars()), 3) self.assertEqual(len(s4p.GetAuthoredPrimvars()), 1) self.assertEqual(len(s4p.GetPrimvarsWithValues()), 1) self.assertEqual(len(s4p.GetPrimvarsWithAuthoredValues()), 1) # Test FindInheritablePrimvars(). self.assertEqual(len(s0p.FindInheritablePrimvars()), 0) self.assertEqual(len(s1p.FindInheritablePrimvars()), 1) self.assertEqual(len(s2p.FindInheritablePrimvars()), 2) self.assertEqual(len(s3p.FindInheritablePrimvars()), 3) self.assertEqual(len(s4p.FindInheritablePrimvars()), 3) # Test FindIncrementallyInheritablePrimvars(). s2_pvars = s2p.FindInheritablePrimvars() s3_pvars = s3p.FindIncrementallyInheritablePrimvars(s2_pvars) self.assertNotEqual(s2_pvars, s3_pvars) self.assertEqual(len(s3_pvars), 3) # Overriding should still force a new set to be created s4_pvars = s4p.FindIncrementallyInheritablePrimvars(s3_pvars) self.assertNotEqual(s3_pvars, s4_pvars) self.assertEqual(len(s4_pvars), 3) # s5p's result should be empty because it neither adds nor blocks/removes # inherited primvars, indicating we should just use the passed-in set s5 = stage.DefinePrim('/s0/s1/s2/s3/s4/s5') s5p = UsdGeom.PrimvarsAPI(s5) s5_pvars = s5p.FindIncrementallyInheritablePrimvars(s4_pvars) self.assertEqual(s5_pvars, []) # Next ensure we can use incrementally computed inheritance to # compute the full set of primvars s5_full = s5p.FindPrimvarsWithInheritance() self.assertEqual(len(s5_full), 3) s5_incr = s5p.FindPrimvarsWithInheritance(s4_pvars) self.assertEqual(set(s5_full), set(s5_incr)) # Test HasPossiblyInheritedPrimvar(). # s0 self.assertFalse(s0p.HasPossiblyInheritedPrimvar('u1')) # s1 self.assertTrue(s1p.HasPossiblyInheritedPrimvar('u1')) # s2 self.assertTrue(s2p.HasPossiblyInheritedPrimvar('u1')) self.assertTrue(s2p.HasPossiblyInheritedPrimvar('u2')) # s3 self.assertTrue(s3p.HasPossiblyInheritedPrimvar('u1')) self.assertTrue(s3p.HasPossiblyInheritedPrimvar('u2')) self.assertTrue(s3p.HasPossiblyInheritedPrimvar('u3')) # s4 self.assertTrue(s4p.HasPossiblyInheritedPrimvar('u1')) self.assertTrue(s4p.HasPossiblyInheritedPrimvar('u2')) self.assertTrue(s4p.HasPossiblyInheritedPrimvar('u3')) # Test FindPrimvarWithInheritance(). # Confirm that an inherited primvar is bound to the source prim, which # may be an ancestor. self.assertFalse(s0p.FindPrimvarWithInheritance('u1')) self.assertEqual( s1p.FindPrimvarWithInheritance('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s2p.FindPrimvarWithInheritance('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s3p.FindPrimvarWithInheritance('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s4p.FindPrimvarWithInheritance('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s4p.FindPrimvarWithInheritance('u2').GetAttr().GetPrim(), s2.GetPrim()) # Confirm that local overrides work self.assertEqual( s4p.FindPrimvarWithInheritance('u3').GetAttr().GetPrim(), s4.GetPrim()) # Confirm the override taking pre-computed inheited primvars works u2_straight = s4p.FindPrimvarWithInheritance('u2') u2_incr = s4p.FindPrimvarWithInheritance('u2', s3p.FindInheritablePrimvars()) self.assertEqual(u2_straight, u2_incr) # Confirm that only constant-interpolation primvars inherit. self.assertEqual(len(s2p.FindInheritablePrimvars()), 2) self.assertTrue(s2p.FindPrimvarWithInheritance('u1')) self.assertTrue(s2p.HasPossiblyInheritedPrimvar('u1')) u1.SetInterpolation(UsdGeom.Tokens.varying) self.assertEqual(len(s2p.FindInheritablePrimvars()), 1) self.assertFalse(s2p.FindPrimvarWithInheritance('u1')) self.assertFalse(s2p.HasPossiblyInheritedPrimvar('u1')) # Confirm that a non-constant primvar blocks inheritance # of ancestral constant primvars of the same name. self.assertEqual(len(s4p.FindInheritablePrimvars()), 2) self.assertTrue(s4p.FindPrimvarWithInheritance('u2')) self.assertTrue(s4p.HasPossiblyInheritedPrimvar('u2')) u2_on_s3 = s3p.CreatePrimvar('u2', Sdf.ValueTypeNames.Float) u2_on_s3.SetInterpolation(UsdGeom.Tokens.varying) u2_on_s3.Set(2.3) self.assertEqual(len(s4p.FindInheritablePrimvars()), 1) self.assertFalse(s4p.FindPrimvarWithInheritance('u2')) self.assertFalse(s4p.HasPossiblyInheritedPrimvar('u2')) # confirm that if a primvar has no authored value, then it behaves # as if not present on the prim, regardless of its interpolation u2_on_s3.GetAttr().Block() self.assertEqual(len(s4p.FindInheritablePrimvars()), 2) self.assertTrue(s4p.FindPrimvarWithInheritance('u2')) self.assertTrue(s4p.HasPossiblyInheritedPrimvar('u2')) # Finally, ensure that builtins like displayColor inherit properly dcp = s1p.CreatePrimvar(UsdGeom.Tokens.primvarsDisplayColor, Sdf.ValueTypeNames.Color3fArray) dcp.Set([(0.5, 0.5, 0.5)]) self.assertEqual( s4p.FindPrimvarWithInheritance( UsdGeom.Tokens.primvarsDisplayColor).GetAttr().GetPrim(), s1.GetPrim())
def test_PrimvarsAPI(self): IsPrimvar = UsdGeom.Primvar.IsPrimvar # We'll put all our Primvar on a single mesh gprim stage = Usd.Stage.CreateInMemory('myTest.usda') gp = UsdGeom.Mesh.Define(stage, '/myMesh') gp_pv = UsdGeom.PrimvarsAPI(gp) nPasses = 3 # Add three Primvars u1 = gp_pv.CreatePrimvar('u_1', Sdf.ValueTypeNames.FloatArray) self.assertFalse(u1.NameContainsNamespaces()) # Make sure it's OK to manually specify the classifier namespace v1 = gp_pv.CreatePrimvar('primvars:v_1', Sdf.ValueTypeNames.FloatArray) self.assertFalse(v1.NameContainsNamespaces()) _3dpmats = gp_pv.CreatePrimvar('projMats', Sdf.ValueTypeNames.Matrix4dArray, "constant", nPasses) # ensure we can create a primvar that contains namespaces! primvarName = 'skel:jointWeights' jointWeights = gp_pv.CreatePrimvar(primvarName, Sdf.ValueTypeNames.FloatArray) self.assertTrue(IsPrimvar(jointWeights)) self.assertTrue(jointWeights.NameContainsNamespaces()) self.assertEqual(primvarName, jointWeights.GetPrimvarName()) # Ensure we cannot create a primvar named indices or any namespace # ending in indices with self.assertRaises(Tf.ErrorException): gp_pv.CreatePrimvar("indices", Sdf.ValueTypeNames.IntArray) with self.assertRaises(Tf.ErrorException): gp_pv.CreatePrimvar("multi:aggregate:indices", Sdf.ValueTypeNames.IntArray) self.assertEqual(len(gp_pv.GetAuthoredPrimvars()), 4) # displayColor and displayOpacity are builtins, not authored self.assertEqual(len(gp_pv.GetPrimvars()), 6) # Now add some random properties, plus a "manually" created, namespaced # primvar, and reverify p = gp.GetPrim() p.CreateRelationship("myBinding") p.CreateAttribute("myColor", Sdf.ValueTypeNames.Color3f) p.CreateAttribute("primvars:some:overly:namespaced:Color", Sdf.ValueTypeNames.Color3f) datas = gp_pv.GetAuthoredPrimvars() self.assertEqual(len(datas), 5) self.assertTrue(IsPrimvar(datas[0])) self.assertTrue(IsPrimvar(datas[1])) # For variety, test the explicit Attribute extractor self.assertTrue(IsPrimvar(datas[2].GetAttr())) self.assertFalse(IsPrimvar(p.GetAttribute("myColor"))) # Here we're testing that the speculative constructor fails properly self.assertFalse(IsPrimvar(UsdGeom.Primvar(p.GetAttribute("myColor")))) # And here that the speculative constructor succeeds properly self.assertTrue( IsPrimvar(UsdGeom.Primvar(p.GetAttribute(v1.GetName())))) # Some of the same tests, exercising the bool-type operator # for UsdGeomPrimvar; Primvar provides the easiest way to get INvalid attrs! self.assertTrue(datas[0]) self.assertTrue(datas[1]) self.assertTrue(datas[2]) self.assertFalse(UsdGeom.Primvar(p.GetAttribute("myColor"))) self.assertFalse(UsdGeom.Primvar(p.GetAttribute("myBinding"))) self.assertTrue(UsdGeom.Primvar(p.GetAttribute(v1.GetName()))) # Same classification test through GprimSchema API self.assertTrue(gp_pv.HasPrimvar('u_1')) self.assertTrue(gp_pv.HasPrimvar('v_1')) self.assertTrue(gp_pv.HasPrimvar('projMats')) self.assertTrue(gp_pv.HasPrimvar('skel:jointWeights')) self.assertFalse(gp_pv.HasPrimvar('myColor')) self.assertFalse(gp_pv.HasPrimvar('myBinding')) # Test that the gpv's returned by GetPrimvars are REALLY valid, # and that the UsdAttribute metadata wrappers work self.assertEqual(datas[0].GetTypeName(), Sdf.ValueTypeNames.Matrix4dArray) self.assertEqual(datas[3].GetTypeName(), Sdf.ValueTypeNames.FloatArray) self.assertEqual(datas[4].GetBaseName(), "v_1") # Now we'll add some extra configuration and verify that the # interrogative API works properly self.assertEqual(u1.GetInterpolation(), UsdGeom.Tokens.constant) # fallback self.assertFalse(u1.HasAuthoredInterpolation()) self.assertFalse(u1.HasAuthoredElementSize()) self.assertTrue(u1.SetInterpolation(UsdGeom.Tokens.vertex)) self.assertTrue(u1.HasAuthoredInterpolation()) self.assertEqual(u1.GetInterpolation(), UsdGeom.Tokens.vertex) self.assertFalse(v1.HasAuthoredInterpolation()) self.assertFalse(v1.HasAuthoredElementSize()) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.uniform)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.varying)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.constant)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.faceVarying)) with self.assertRaises(Tf.ErrorException): v1.SetInterpolation("frobosity") # Should be the last good value set self.assertEqual(v1.GetInterpolation(), "faceVarying") self.assertTrue(_3dpmats.HasAuthoredInterpolation()) self.assertTrue(_3dpmats.HasAuthoredElementSize()) with self.assertRaises(Tf.ErrorException): _3dpmats.SetElementSize(0) # Failure to set shouldn't change the state... self.assertTrue(_3dpmats.HasAuthoredElementSize()) self.assertTrue(_3dpmats.SetElementSize(nPasses)) self.assertTrue(_3dpmats.HasAuthoredElementSize()) # Make sure value Get/Set work self.assertEqual(u1.Get(), None) self.assertFalse(u1.IsIndexed()) self.assertFalse(u1.GetIndicesAttr()) self.assertEqual(u1.ComputeFlattened(), None) uVal = Vt.FloatArray([1.1, 2.1, 3.1]) self.assertTrue(u1.Set(uVal)) self.assertEqual(u1.Get(), uVal) # Make sure indexed primvars work self.assertFalse(u1.IsIndexed()) indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) self.assertTrue(u1.SetIndices(indices)) self.assertTrue(u1.IsIndexed()) self.assertTrue(u1.GetIndicesAttr()) self.assertEqual(u1.GetIndices(), indices) for a, b in zip(u1.ComputeFlattened(), [1.1, 2.1, 3.1, 3.1, 2.1, 1.1]): self.assertTrue(Gf.IsClose(a, b, 1e-5)) self.assertNotEqual(u1.ComputeFlattened(), u1.Get()) indicesWithInvalid = Vt.IntArray([0, 3, 2, 2, -1, 0]) self.assertTrue(u1.SetIndices(indicesWithInvalid)) self.assertTrue(u1.ComputeFlattened() is None) indicesWithInvalid = Vt.IntArray([4, 5, 6, 7, -1, 8]) self.assertTrue(u1.SetIndices(indicesWithInvalid)) self.assertTrue(u1.ComputeFlattened() is None) self.assertEqual(u1.GetUnauthoredValuesIndex(), -1) self.assertTrue(u1.SetUnauthoredValuesIndex(2)) self.assertEqual(u1.GetUnauthoredValuesIndex(), 2) self.assertEqual(u1.GetTimeSamples(), []) self.assertFalse(u1.ValueMightBeTimeVarying()) indicesAt1 = Vt.IntArray([1, 2, 0]) indicesAt2 = Vt.IntArray([]) uValAt1 = Vt.FloatArray([2.1, 3.1, 4.1]) uValAt2 = Vt.FloatArray([3.1, 4.1, 5.1]) self.assertTrue(u1.SetIndices(indicesAt1, 1.0)) self.assertEqual(u1.GetIndices(1.0), indicesAt1) self.assertTrue(u1.Set(uValAt1, 1.0)) self.assertEqual(u1.Get(1.0), uValAt1) self.assertEqual(u1.GetTimeSamples(), [1.0]) self.assertFalse(u1.ValueMightBeTimeVarying()) self.assertTrue(u1.SetIndices(indicesAt2, 2.0)) self.assertEqual(u1.GetIndices(2.0), indicesAt2) self.assertTrue(u1.Set(uValAt2, 2.0)) self.assertEqual(u1.Get(2.0), uValAt2) self.assertEqual(u1.GetTimeSamples(), [1.0, 2.0]) self.assertEqual(u1.GetTimeSamplesInInterval(Gf.Interval(0.5, 1.5)), [1.0]) self.assertTrue(u1.ValueMightBeTimeVarying()) # Add more time-samples to u1 indicesAt0 = Vt.IntArray([]) uValAt3 = Vt.FloatArray([4.1, 5.1, 6.1]) self.assertTrue(u1.SetIndices(indicesAt0, 0.0)) self.assertEqual(u1.GetTimeSamples(), [0.0, 1.0, 2.0]) self.assertTrue(u1.Set(uValAt3, 3.0)) self.assertEqual(u1.GetTimeSamples(), [0.0, 1.0, 2.0, 3.0]) self.assertEqual(u1.GetTimeSamplesInInterval(Gf.Interval(1.5, 3.5)), [2.0, 3.0]) for a, b in zip(u1.ComputeFlattened(1.0), [3.1, 4.1, 2.1]): self.assertTrue(Gf.IsClose(a, b, 1e-5)) self.assertNotEqual(u1.ComputeFlattened(1.0), u1.Get(1.0)) self.assertTrue(len(u1.ComputeFlattened(2.0)) == 0) self.assertNotEqual(u1.ComputeFlattened(2.0), u1.Get(2.0)) # Ensure that primvars with indices only authored at timeSamples # (i.e. no default) are recognized as such. Manual name-munging # necessitated by UsdGeomPrimvar's lack of API for accessing # the indices attribute directly! u1Indices = p.GetAttribute(u1.GetName() + ":indices") self.assertTrue(u1Indices) u1Indices.ClearDefault() self.assertTrue(u1.IsIndexed()) # Finally, ensure the values returned by GetDeclarationInfo # (on new Primvar objects, to test the GprimSchema API) # is identical to the individual queries, and matches what we set above nu1 = gp_pv.GetPrimvar("u_1") (name, typeName, interpolation, elementSize) = nu1.GetDeclarationInfo() self.assertEqual(name, u1.GetBaseName()) self.assertEqual(typeName, u1.GetTypeName()) self.assertEqual(interpolation, u1.GetInterpolation()) self.assertEqual(elementSize, u1.GetElementSize()) self.assertEqual(name, "u_1") self.assertEqual(typeName, Sdf.ValueTypeNames.FloatArray) self.assertEqual(interpolation, UsdGeom.Tokens.vertex) self.assertEqual(elementSize, 1) nv1 = gp_pv.GetPrimvar("v_1") (name, typeName, interpolation, elementSize) = nv1.GetDeclarationInfo() self.assertEqual(name, v1.GetBaseName()) self.assertEqual(typeName, v1.GetTypeName()) self.assertEqual(interpolation, v1.GetInterpolation()) self.assertEqual(elementSize, v1.GetElementSize()) self.assertEqual(name, "v_1") self.assertEqual(typeName, Sdf.ValueTypeNames.FloatArray) self.assertEqual(interpolation, UsdGeom.Tokens.faceVarying) self.assertEqual(elementSize, 1) nmats = gp_pv.GetPrimvar('projMats') (name, typeName, interpolation, elementSize) = nmats.GetDeclarationInfo() self.assertEqual(name, _3dpmats.GetBaseName()) self.assertEqual(typeName, _3dpmats.GetTypeName()) self.assertEqual(interpolation, _3dpmats.GetInterpolation()) self.assertEqual(elementSize, _3dpmats.GetElementSize()) self.assertEqual(name, 'projMats') self.assertEqual(typeName, Sdf.ValueTypeNames.Matrix4dArray) self.assertEqual(interpolation, UsdGeom.Tokens.constant) self.assertEqual(elementSize, nPasses) # Custom builtins for gprim display primvars displayColor = gp.CreateDisplayColorPrimvar(UsdGeom.Tokens.vertex, 3) self.assertTrue(displayColor) declInfo = displayColor.GetDeclarationInfo() self.assertEqual(declInfo, ('displayColor', Sdf.ValueTypeNames.Color3fArray, UsdGeom.Tokens.vertex, 3)) displayOpacity = gp.CreateDisplayOpacityPrimvar( UsdGeom.Tokens.constant) self.assertTrue(displayOpacity) declInfo = displayOpacity.GetDeclarationInfo() self.assertEqual(declInfo, ('displayOpacity', Sdf.ValueTypeNames.FloatArray, UsdGeom.Tokens.constant, 1)) # Id primvar notId = gp_pv.CreatePrimvar('notId', Sdf.ValueTypeNames.FloatArray) self.assertFalse(notId.IsIdTarget()) with self.assertRaises(Tf.ErrorException): notId.SetIdTarget(gp.GetPath()) handleid = gp_pv.CreatePrimvar('handleid', Sdf.ValueTypeNames.String) # make sure we can still just set a string v = "handleid_value" self.assertTrue(handleid.Set(v)) self.assertEqual(handleid.Get(), v) self.assertEqual(handleid.ComputeFlattened(), v) numPrimvars = len(gp_pv.GetPrimvars()) # This check below ensures that the "indices" attributes belonging to # indexed primvars aren't considered to be primvars themselves. self.assertEqual(numPrimvars, 9) self.assertTrue(handleid.SetIdTarget(gp.GetPath())) # make sure we didn't increase the number of primvars (also that # GetPrimvars doesn't break when we have relationships) self.assertEqual(len(gp_pv.GetPrimvars()), numPrimvars) self.assertEqual(handleid.Get(), gp.GetPath()) stringPath = '/my/string/path' self.assertTrue(handleid.SetIdTarget(stringPath)) self.assertEqual(handleid.Get(), Sdf.Path(stringPath)) p = Sdf.Path('/does/not/exist') self.assertTrue(handleid.SetIdTarget(p)) self.assertEqual(handleid.Get(), p) handleid_array = gp_pv.CreatePrimvar('handleid_array', Sdf.ValueTypeNames.StringArray) self.assertTrue(handleid_array.SetIdTarget(gp.GetPath()))
def test_PrimvarInheritance(self): stage = Usd.Stage.CreateInMemory('primvarInheritance.usda') s0 = UsdGeom.Mesh.Define(stage, '/s0') s1 = UsdGeom.Mesh.Define(stage, '/s0/s1') s2 = UsdGeom.Mesh.Define(stage, '/s0/s1/s2') s3 = UsdGeom.Mesh.Define(stage, '/s0/s1/s2/s3') s4 = UsdGeom.Mesh.Define(stage, '/s0/s1/s2/s3/s4') s0p = UsdGeom.PrimvarsAPI(s0) s1p = UsdGeom.PrimvarsAPI(s1) s2p = UsdGeom.PrimvarsAPI(s2) s3p = UsdGeom.PrimvarsAPI(s3) s4p = UsdGeom.PrimvarsAPI(s4) u1 = s1p.CreatePrimvar('u1', Sdf.ValueTypeNames.Float) u1.SetInterpolation(UsdGeom.Tokens.constant) u1.Set(1) u2 = s2p.CreatePrimvar('u2', Sdf.ValueTypeNames.Float) u2.SetInterpolation(UsdGeom.Tokens.constant) u2.Set(2) u3 = s3p.CreatePrimvar('u3', Sdf.ValueTypeNames.Float) u3.SetInterpolation(UsdGeom.Tokens.constant) u3.Set(3) # u4 overrides u3 on prim s4. u4 = s4p.CreatePrimvar('u3', Sdf.ValueTypeNames.Float) u4.SetInterpolation(UsdGeom.Tokens.constant) u4.Set(4) # Test FindInheritedPrimvars(). self.assertEqual(len(s0p.FindInheritedPrimvars()), 0) self.assertEqual(len(s1p.FindInheritedPrimvars()), 0) self.assertEqual(len(s2p.FindInheritedPrimvars()), 1) self.assertEqual(len(s3p.FindInheritedPrimvars()), 2) self.assertEqual(len(s4p.FindInheritedPrimvars()), 2) # Test HasInheritedPrimvar(). # s0 self.assertFalse(s0p.HasInheritedPrimvar('u1')) # s1 self.assertFalse(s1p.HasInheritedPrimvar('u1')) # s2 self.assertTrue(s2p.HasInheritedPrimvar('u1')) self.assertFalse(s2p.HasInheritedPrimvar('u2')) # s3 self.assertTrue(s3p.HasInheritedPrimvar('u1')) self.assertTrue(s3p.HasInheritedPrimvar('u2')) self.assertFalse(s3p.HasInheritedPrimvar('u3')) # s4 self.assertTrue(s4p.HasInheritedPrimvar('u1')) self.assertTrue(s4p.HasInheritedPrimvar('u2')) self.assertFalse(s4p.HasInheritedPrimvar('u3')) # set locally! # Test FindInheritedPrimvar(). # Confirm that an inherited primvar is bound to the source prim, which # may be an ancestor. self.assertFalse(s0p.FindInheritedPrimvar('u1')) self.assertFalse(s1p.FindInheritedPrimvar('u1')) self.assertEqual( s2p.FindInheritedPrimvar('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s3p.FindInheritedPrimvar('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s4p.FindInheritedPrimvar('u1').GetAttr().GetPrim(), s1.GetPrim()) self.assertEqual( s4p.FindInheritedPrimvar('u2').GetAttr().GetPrim(), s2.GetPrim()) # Confirm that if the primvar is overriden locally, it does not # also get found as an inherited primvar. self.assertFalse(s4p.FindInheritedPrimvar('u3'))
def test_PrimvarsAPI(self): IsPrimvar = UsdGeom.Primvar.IsPrimvar # We'll put all our Primvar on a single mesh gprim stage = Usd.Stage.CreateInMemory('myTest.usda') gp = UsdGeom.Mesh.Define(stage, '/myMesh') gp_pv = UsdGeom.PrimvarsAPI(gp) nPasses = 3 # Add three Primvars u1 = gp_pv.CreatePrimvar('u_1', Sdf.ValueTypeNames.FloatArray) self.assertFalse(u1.NameContainsNamespaces()) self.assertEqual(UsdGeom.Primvar.StripPrimvarsName(u1.GetName()), "u_1") # Make sure it's OK to manually specify the classifier namespace v1 = gp_pv.CreatePrimvar('primvars:v_1', Sdf.ValueTypeNames.FloatArray) self.assertEqual(UsdGeom.Primvar.StripPrimvarsName(v1.GetName()), "v_1") noPrimvarsPrefixName = "noPrimvarPrefixName" self.assertEqual( UsdGeom.Primvar.StripPrimvarsName(noPrimvarsPrefixName), noPrimvarsPrefixName) self.assertFalse(v1.NameContainsNamespaces()) _3dpmats = gp_pv.CreatePrimvar('projMats', Sdf.ValueTypeNames.Matrix4dArray, "constant", nPasses) # ensure we can create a primvar that contains namespaces! primvarName = 'skel:jointWeights' jointWeights = gp_pv.CreatePrimvar(primvarName, Sdf.ValueTypeNames.FloatArray) self.assertTrue(IsPrimvar(jointWeights)) self.assertTrue( UsdGeom.Primvar.IsValidPrimvarName(jointWeights.GetName())) self.assertTrue(jointWeights.NameContainsNamespaces()) self.assertEqual(primvarName, jointWeights.GetPrimvarName()) # Ensure we cannot create a primvar named indices or any namespace # ending in indices with self.assertRaises(Tf.ErrorException): gp_pv.CreatePrimvar("indices", Sdf.ValueTypeNames.IntArray) with self.assertRaises(Tf.ErrorException): gp_pv.CreatePrimvar("multi:aggregate:indices", Sdf.ValueTypeNames.IntArray) self.assertEqual(len(gp_pv.GetAuthoredPrimvars()), 4) # displayColor and displayOpacity are builtins, not authored self.assertEqual(len(gp_pv.GetPrimvars()), 6) # Now add some random properties, plus a "manually" created, namespaced # primvar, and reverify p = gp.GetPrim() p.CreateRelationship("myBinding") p.CreateAttribute("myColor", Sdf.ValueTypeNames.Color3f) p.CreateAttribute("primvars:some:overly:namespaced:Color", Sdf.ValueTypeNames.Color3f) datas = gp_pv.GetAuthoredPrimvars() self.assertEqual(len(datas), 5) self.assertTrue(IsPrimvar(datas[0])) self.assertTrue(UsdGeom.Primvar.IsValidPrimvarName(datas[0].GetName())) self.assertTrue( UsdGeom.Primvar.IsPrimvarRelatedPropertyName(datas[0].GetName())) self.assertTrue(IsPrimvar(datas[1])) self.assertTrue(UsdGeom.Primvar.IsValidPrimvarName(datas[1].GetName())) self.assertTrue( UsdGeom.Primvar.IsPrimvarRelatedPropertyName(datas[1].GetName())) # For variety, test the explicit Attribute extractor self.assertTrue(IsPrimvar(datas[2].GetAttr())) self.assertTrue( UsdGeom.Primvar.IsValidPrimvarName(datas[2].GetAttr().GetName())) self.assertTrue( UsdGeom.Primvar.IsPrimvarRelatedPropertyName( datas[2].GetAttr().GetName())) self.assertFalse(IsPrimvar(p.GetAttribute("myColor"))) self.assertFalse(UsdGeom.Primvar.IsValidPrimvarName("myColor")) self.assertFalse( UsdGeom.Primvar.IsPrimvarRelatedPropertyName("myColor")) # Here we're testing that the speculative constructor fails properly self.assertFalse(IsPrimvar(UsdGeom.Primvar(p.GetAttribute("myColor")))) self.assertFalse( UsdGeom.Primvar.IsValidPrimvarName( datas[0].GetIndicesAttr().GetName())) self.assertTrue( UsdGeom.Primvar.IsPrimvarRelatedPropertyName( datas[0].GetIndicesAttr().GetName())) # And here that the speculative constructor succeeds properly self.assertTrue( IsPrimvar(UsdGeom.Primvar(p.GetAttribute(v1.GetName())))) # Some of the same tests, exercising the bool-type operator # for UsdGeomPrimvar; Primvar provides the easiest way to get INvalid attrs! self.assertTrue(datas[0]) self.assertTrue(datas[1]) self.assertTrue(datas[2]) self.assertFalse(UsdGeom.Primvar(p.GetAttribute("myColor"))) self.assertFalse(UsdGeom.Primvar(p.GetAttribute("myBinding"))) self.assertTrue(UsdGeom.Primvar(p.GetAttribute(v1.GetName()))) # Same classification test through GprimSchema API self.assertTrue(gp_pv.HasPrimvar('u_1')) self.assertTrue(gp_pv.HasPrimvar('v_1')) self.assertTrue(gp_pv.HasPrimvar('projMats')) self.assertTrue(gp_pv.HasPrimvar('skel:jointWeights')) self.assertFalse(gp_pv.HasPrimvar('myColor')) self.assertFalse(gp_pv.HasPrimvar('myBinding')) # Test that the gpv's returned by GetPrimvars are REALLY valid, # and that the UsdAttribute metadata wrappers work self.assertEqual(datas[0].GetTypeName(), Sdf.ValueTypeNames.Matrix4dArray) self.assertEqual(datas[3].GetTypeName(), Sdf.ValueTypeNames.FloatArray) self.assertEqual(datas[4].GetBaseName(), "v_1") # Now we'll add some extra configuration and verify that the # interrogative API works properly self.assertEqual(u1.GetInterpolation(), UsdGeom.Tokens.constant) # fallback self.assertFalse(u1.HasAuthoredInterpolation()) self.assertFalse(u1.HasAuthoredElementSize()) self.assertTrue(u1.SetInterpolation(UsdGeom.Tokens.vertex)) self.assertTrue(u1.HasAuthoredInterpolation()) self.assertEqual(u1.GetInterpolation(), UsdGeom.Tokens.vertex) self.assertFalse(v1.HasAuthoredInterpolation()) self.assertFalse(v1.HasAuthoredElementSize()) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.uniform)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.varying)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.constant)) self.assertTrue(v1.SetInterpolation(UsdGeom.Tokens.faceVarying)) with self.assertRaises(Tf.ErrorException): v1.SetInterpolation("frobosity") # Should be the last good value set self.assertEqual(v1.GetInterpolation(), "faceVarying") self.assertTrue(_3dpmats.HasAuthoredInterpolation()) self.assertTrue(_3dpmats.HasAuthoredElementSize()) with self.assertRaises(Tf.ErrorException): _3dpmats.SetElementSize(0) # Failure to set shouldn't change the state... self.assertTrue(_3dpmats.HasAuthoredElementSize()) self.assertTrue(_3dpmats.SetElementSize(nPasses)) self.assertTrue(_3dpmats.HasAuthoredElementSize()) # Make sure value Get/Set work self.assertEqual(u1.Get(), None) self.assertFalse(u1.IsIndexed()) self.assertFalse(u1.GetIndicesAttr()) self.assertEqual(u1.ComputeFlattened(), None) uVal = Vt.FloatArray([1.1, 2.1, 3.1]) self.assertTrue(u1.Set(uVal)) self.assertEqual(u1.Get(), uVal) # Make sure indexed primvars work self.assertFalse(u1.IsIndexed()) indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) self.assertTrue(u1.SetIndices(indices)) self.assertTrue(u1.IsIndexed()) self.assertTrue(u1.GetIndicesAttr()) self.assertEqual(u1.GetIndices(), indices) for a, b in zip(u1.ComputeFlattened(), [1.1, 2.1, 3.1, 3.1, 2.1, 1.1]): self.assertTrue(Gf.IsClose(a, b, 1e-5)) self.assertNotEqual(u1.ComputeFlattened(), u1.Get()) indicesWithInvalid = Vt.IntArray([0, 3, 2, 2, -1, 0]) self.assertTrue(u1.SetIndices(indicesWithInvalid)) self.assertTrue(u1.ComputeFlattened() is None) indicesWithInvalid = Vt.IntArray([4, 5, 6, 7, -1, 8]) self.assertTrue(u1.SetIndices(indicesWithInvalid)) self.assertTrue(u1.ComputeFlattened() is None) self.assertEqual(u1.GetUnauthoredValuesIndex(), -1) self.assertTrue(u1.SetUnauthoredValuesIndex(2)) self.assertEqual(u1.GetUnauthoredValuesIndex(), 2) self.assertEqual(u1.GetTimeSamples(), []) self.assertFalse(u1.ValueMightBeTimeVarying()) indicesAt1 = Vt.IntArray([1, 2, 0]) indicesAt2 = Vt.IntArray([]) uValAt1 = Vt.FloatArray([2.1, 3.1, 4.1]) uValAt2 = Vt.FloatArray([3.1, 4.1, 5.1]) self.assertTrue(u1.SetIndices(indicesAt1, 1.0)) self.assertEqual(u1.GetIndices(1.0), indicesAt1) self.assertTrue(u1.Set(uValAt1, 1.0)) self.assertEqual(u1.Get(1.0), uValAt1) self.assertEqual(u1.GetTimeSamples(), [1.0]) self.assertFalse(u1.ValueMightBeTimeVarying()) self.assertTrue(u1.SetIndices(indicesAt2, 2.0)) self.assertEqual(u1.GetIndices(2.0), indicesAt2) self.assertTrue(u1.Set(uValAt2, 2.0)) self.assertEqual(u1.Get(2.0), uValAt2) self.assertEqual(u1.GetTimeSamples(), [1.0, 2.0]) self.assertEqual(u1.GetTimeSamplesInInterval(Gf.Interval(0.5, 1.5)), [1.0]) self.assertTrue(u1.ValueMightBeTimeVarying()) # Add more time-samples to u1 indicesAt0 = Vt.IntArray([]) uValAt3 = Vt.FloatArray([4.1, 5.1, 6.1]) self.assertTrue(u1.SetIndices(indicesAt0, 0.0)) self.assertEqual(u1.GetTimeSamples(), [0.0, 1.0, 2.0]) self.assertTrue(u1.Set(uValAt3, 3.0)) self.assertEqual(u1.GetTimeSamples(), [0.0, 1.0, 2.0, 3.0]) self.assertEqual(u1.GetTimeSamplesInInterval(Gf.Interval(1.5, 3.5)), [2.0, 3.0]) for a, b in zip(u1.ComputeFlattened(1.0), [3.1, 4.1, 2.1]): self.assertTrue(Gf.IsClose(a, b, 1e-5)) self.assertNotEqual(u1.ComputeFlattened(1.0), u1.Get(1.0)) self.assertTrue(len(u1.ComputeFlattened(2.0)) == 0) self.assertNotEqual(u1.ComputeFlattened(2.0), u1.Get(2.0)) # Ensure that primvars with indices only authored at timeSamples # (i.e. no default) are recognized as such. u1Indices = u1.GetIndicesAttr() self.assertTrue(u1Indices) u1Indices.ClearDefault() self.assertTrue(u1.IsIndexed()) # Finally, ensure the values returned by GetDeclarationInfo # (on new Primvar objects, to test the GprimSchema API) # is identical to the individual queries, and matches what we set above nu1 = gp_pv.GetPrimvar("u_1") (name, typeName, interpolation, elementSize) = nu1.GetDeclarationInfo() self.assertEqual(name, u1.GetBaseName()) self.assertEqual(typeName, u1.GetTypeName()) self.assertEqual(interpolation, u1.GetInterpolation()) self.assertEqual(elementSize, u1.GetElementSize()) self.assertEqual(name, "u_1") self.assertEqual(typeName, Sdf.ValueTypeNames.FloatArray) self.assertEqual(interpolation, UsdGeom.Tokens.vertex) self.assertEqual(elementSize, 1) nv1 = gp_pv.GetPrimvar("v_1") (name, typeName, interpolation, elementSize) = nv1.GetDeclarationInfo() self.assertEqual(name, v1.GetBaseName()) self.assertEqual(typeName, v1.GetTypeName()) self.assertEqual(interpolation, v1.GetInterpolation()) self.assertEqual(elementSize, v1.GetElementSize()) self.assertEqual(name, "v_1") self.assertEqual(typeName, Sdf.ValueTypeNames.FloatArray) self.assertEqual(interpolation, UsdGeom.Tokens.faceVarying) self.assertEqual(elementSize, 1) nmats = gp_pv.GetPrimvar('projMats') (name, typeName, interpolation, elementSize) = nmats.GetDeclarationInfo() self.assertEqual(name, _3dpmats.GetBaseName()) self.assertEqual(typeName, _3dpmats.GetTypeName()) self.assertEqual(interpolation, _3dpmats.GetInterpolation()) self.assertEqual(elementSize, _3dpmats.GetElementSize()) self.assertEqual(name, 'projMats') self.assertEqual(typeName, Sdf.ValueTypeNames.Matrix4dArray) self.assertEqual(interpolation, UsdGeom.Tokens.constant) self.assertEqual(elementSize, nPasses) # Custom builtins for gprim display primvars displayColor = gp.CreateDisplayColorPrimvar(UsdGeom.Tokens.vertex, 3) self.assertTrue(displayColor) declInfo = displayColor.GetDeclarationInfo() self.assertEqual(declInfo, ('displayColor', Sdf.ValueTypeNames.Color3fArray, UsdGeom.Tokens.vertex, 3)) displayOpacity = gp.CreateDisplayOpacityPrimvar( UsdGeom.Tokens.constant) self.assertTrue(displayOpacity) declInfo = displayOpacity.GetDeclarationInfo() self.assertEqual(declInfo, ('displayOpacity', Sdf.ValueTypeNames.FloatArray, UsdGeom.Tokens.constant, 1)) # Id primvar notId = gp_pv.CreatePrimvar('notId', Sdf.ValueTypeNames.FloatArray) self.assertFalse(notId.IsIdTarget()) with self.assertRaises(Tf.ErrorException): notId.SetIdTarget(gp.GetPath()) handleid = gp_pv.CreatePrimvar('handleid', Sdf.ValueTypeNames.String) # make sure we can still just set a string v = "handleid_value" self.assertTrue(handleid.Set(v)) self.assertEqual(handleid.Get(), v) self.assertEqual(handleid.ComputeFlattened(), v) numPrimvars = len(gp_pv.GetPrimvars()) # This check below ensures that the "indices" attributes belonging to # indexed primvars aren't considered to be primvars themselves. self.assertEqual(numPrimvars, 9) self.assertTrue(handleid.SetIdTarget(gp.GetPath())) # make sure we didn't increase the number of primvars (also that # GetPrimvars doesn't break when we have relationships) self.assertEqual(len(gp_pv.GetPrimvars()), numPrimvars) self.assertEqual(handleid.Get(), gp.GetPath()) stringPath = '/my/string/path' self.assertTrue(handleid.SetIdTarget(stringPath)) self.assertEqual(handleid.Get(), Sdf.Path(stringPath)) p = Sdf.Path('/does/not/exist') self.assertTrue(handleid.SetIdTarget(p)) self.assertEqual(handleid.Get(), p) handleid_array = gp_pv.CreatePrimvar('handleid_array', Sdf.ValueTypeNames.StringArray) self.assertTrue(handleid_array.SetIdTarget(gp.GetPath())) # Test BlockPrimvar API pv_blocking = gp_pv.CreatePrimvar('pvb', Sdf.ValueTypeNames.FloatArray) pvName = pv_blocking.GetName() pv_blocking.SetInterpolation(UsdGeom.Tokens.vertex) pv_val = Vt.FloatArray([1.1, 2.1, 3.1]) pv_blocking.Set(pv_val) # Block a non-indexed primvar should also construct and block indices attr self.assertFalse(pv_blocking.IsIndexed()) self.assertTrue(pv_blocking.HasAuthoredValue()) self.assertTrue(pv_blocking.HasAuthoredInterpolation()) gp_pv.BlockPrimvar(pvName) self.assertFalse(pv_blocking.HasAuthoredValue()) self.assertTrue(pv_blocking.HasAuthoredInterpolation()) self.assertFalse(pv_blocking.IsIndexed()) self.assertTrue( pv_blocking.GetIndicesAttr().GetResolveInfo().ValueIsBlocked()) # re-set pv_blocking pv_blocking.Set(pv_val) pv_indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) pv_blocking.SetIndices(pv_indices) self.assertTrue(pv_blocking.HasAuthoredValue()) self.assertTrue(pv_blocking.HasAuthoredInterpolation()) self.assertTrue(pv_blocking.IsIndexed()) # Block primvar as well as indices Attr gp_pv.BlockPrimvar(pvName) self.assertFalse(pv_blocking.HasAuthoredValue()) self.assertTrue(pv_blocking.HasAuthoredInterpolation()) self.assertFalse(pv_blocking.IsIndexed()) # re-set pv_blocking for further testing pv_blocking.Set(pv_val) pv_indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) pv_blocking.SetIndices(pv_indices) # test BlockPrimvar on a referenced prim weakLayer = Sdf.Layer.CreateAnonymous() stageWeak = Usd.Stage.Open(weakLayer) ovrMesh = stageWeak.OverridePrim('/myMesh') ovrMesh.GetReferences().AddReference(stage.GetRootLayer().identifier, '/myMesh') gp_pv_ovr = UsdGeom.PrimvarsAPI(ovrMesh) pv_blocking_ovr = gp_pv_ovr.GetPrimvar(pvName) self.assertTrue(pv_blocking_ovr.HasAuthoredValue()) self.assertTrue(pv_blocking_ovr.HasAuthoredInterpolation()) self.assertTrue(pv_blocking_ovr.IsIndexed()) # should only block primvar and indices attr in the referenced prim gp_pv_ovr.BlockPrimvar(pvName) # ovr primvar will be blocked! self.assertFalse(pv_blocking_ovr.HasAuthoredValue()) self.assertTrue(pv_blocking_ovr.HasAuthoredInterpolation()) self.assertFalse(pv_blocking_ovr.IsIndexed()) # stronger layer wont get affected and original prim should not be blocked self.assertTrue(pv_blocking.HasAuthoredValue()) self.assertTrue(pv_blocking.HasAuthoredInterpolation()) self.assertTrue(pv_blocking.IsIndexed()) # Remove a few valid primvar names # without namespace p = gp.GetPrim() self.assertTrue(u1.IsIndexed()) u1Name = u1.GetName() u1IndicesAttrName = u1.GetIndicesAttr().GetName() # can not remove a primvar across a reference arc weakLayer = Sdf.Layer.CreateAnonymous() stageWeak = Usd.Stage.Open(weakLayer) ovrMesh = stageWeak.OverridePrim('/myMesh') ovrMesh.GetReferences().AddReference(stage.GetRootLayer().identifier, '/myMesh') gp_pv_ovr = UsdGeom.PrimvarsAPI(ovrMesh) self.assertTrue(gp_pv_ovr.HasPrimvar(u1Name)) self.assertFalse(gp_pv_ovr.RemovePrimvar(u1Name)) self.assertTrue(gp_pv_ovr.GetPrim().HasAttribute(u1Name)) # remove indexed primvar self.assertTrue(gp_pv.RemovePrimvar(u1Name)) self.assertFalse(p.HasAttribute(u1Name)) self.assertFalse(p.HasAttribute(u1IndicesAttrName)) # with primvars namespace v1Name = v1.GetName() self.assertTrue(gp_pv.RemovePrimvar(v1Name)) self.assertFalse(p.HasAttribute(v1Name)) # primvar does not exists self.assertFalse(gp_pv.RemovePrimvar('does_not_exist')) self.assertFalse(gp_pv.RemovePrimvar('does_not_exist:does_not_exist')) # try to remove an invalid primvar with restricted tokens, "indices" with self.assertRaises(Tf.ErrorException): gp_pv.RemovePrimvar('indices') with self.assertRaises(Tf.ErrorException): gp_pv.RemovePrimvar('multi:aggregate:indices') # create Indices primvar using CreateIndexedPrimvar API uVal = Vt.FloatArray([1.1, 2.1, 3.1]) indices = Vt.IntArray([0, 1, 2, 2, 1, 0]) indexedPrimvar = gp_pv.CreateIndexedPrimvar( 'indexedPrimvar', Sdf.ValueTypeNames.FloatArray, uVal, indices, UsdGeom.Tokens.vertex) self.assertTrue(indexedPrimvar.IsIndexed()) self.assertTrue(indexedPrimvar.HasAuthoredValue()) self.assertTrue(indexedPrimvar.HasAuthoredInterpolation()) # mimic a Pixar production workflow of creating primvars # 1. show usage with CreatePrimvar # 2. show usage with CreateNonIndexedPrimvar # - create a primvar in base layer # - override this primvar in a stronger layer # - update primvar in base layer to use indices # - test if primvar has indices blocked in strong layer or not! # Create primvar in base layer using CreatePrimvar api and set value basePrimvar1 = gp_pv.CreatePrimvar('pv1', Sdf.ValueTypeNames.FloatArray) basePrimvar1.Set(uVal) # Create primvar in base layer using CreatePrimvar api and set value basePrimvar2 = gp_pv.CreatePrimvar('pv2', Sdf.ValueTypeNames.FloatArray) basePrimvar2.Set(uVal) # stronger layer strongLayer = Sdf.Layer.CreateAnonymous() strongStage = Usd.Stage.Open(strongLayer) # over Mesh prim and add reference oMesh = strongStage.OverridePrim('/myMesh') oMesh.GetReferences().AddReference(stage.GetRootLayer().identifier, '/myMesh') # over primvarsApi instance gp_pv_ovr = UsdGeom.PrimvarsAPI(oMesh) # override value for primvar oVal = Vt.FloatArray([2.2, 3.2, 4.2]) # override pv1 using CreatePrimvar api oBasePrimvar1 = gp_pv_ovr.CreatePrimvar('pv1', Sdf.ValueTypeNames.FloatArray) oBasePrimvar1.Set(oVal) # override pv2 using CreateNonIndexedPrimvar api oBasePrimvar2 = gp_pv_ovr.CreateNonIndexedPrimvar( 'pv2', Sdf.ValueTypeNames.FloatArray, oVal) # test indices attr missing on oBasePrimvar1 self.assertFalse(oBasePrimvar1.GetIndicesAttr().IsValid()) # test oBasePrimvar2's indices attribute has a block authored self.assertFalse(oBasePrimvar2.IsIndexed()) self.assertTrue( oBasePrimvar2.GetIndicesAttr().GetResolveInfo().ValueIsBlocked()) # update base (weaker) layer primvars to have an indices basePrimvar1.SetIndices(indices) basePrimvar2.SetIndices(indices) # ovr pv1 should now get indices self.assertTrue(oBasePrimvar1.IsIndexed()) # ovr pv2 should still have the block for indices self.assertFalse(oBasePrimvar2.IsIndexed()) self.assertTrue( oBasePrimvar2.GetIndicesAttr().GetResolveInfo().ValueIsBlocked())
def add_voxelgrid(stage, voxelgrid, scene_path, time=None): r"""Add a voxelgrid to an existing USD stage. Add a voxelgrid where occupied voxels are defined by non-zero values. The voxelgrid is represented by point instances of a cube centered at each occupied index coordinate and scaled. The stage is modified but not saved to disk. Args: stage (Usd.Stage): Stage onto which to add the voxelgrid. voxelgrid (torch.BoolTensor): Binary voxelgrid of shape ``(N, N, N)``. scene_path (str): Absolute path of voxelgrid within the USD file scene. Must be a valid Sdf.Path. 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') >>> voxelgrid = torch.rand(32, 32, 32) > 0.5 >>> stage = add_voxelgrid(stage, voxelgrid, '/World/VoxelGrids/voxelgrid_0') >>> stage.Save() """ scene_path = Sdf.Path(scene_path) if time is None: time = Usd.TimeCode.Default() if stage.GetPrimAtPath(scene_path): instancer_prim = stage.GetPrimAtPath(scene_path) else: instancer_prim = stage.DefinePrim(scene_path, 'PointInstancer') instancer = UsdGeom.PointInstancer(instancer_prim) assert instancer cube = UsdGeom.Cube.Define(stage, f'{scene_path}/cube') cube.GetSizeAttr().Set(1.0) instancer.CreatePrototypesRel().SetTargets([cube.GetPath()]) # Get each occupied voxel's centre coordinate points = torch.nonzero(voxelgrid, as_tuple=False).float() # Generate instancer parameters indices = [0] * points.shape[0] positions = points.cpu().tolist() scales = [(1.,) * 3] * points.size(0) # Populate point instancer instancer.GetProtoIndicesAttr().Set(indices, time=time) instancer.GetPositionsAttr().Set(positions, time=time) instancer.GetScalesAttr().Set(scales, time=time) # Centre at (0, 0, 0) and scale points adjusted_scale = 1. / (voxelgrid.size(0) - 1) scale_op = instancer.GetPrim().GetAttribute('xformOp:scale') if not scale_op: scale_op = UsdGeom.Xformable(instancer).AddScaleOp() scale_op.Set((adjusted_scale,) * 3, time=time) translate_op = instancer.GetPrim().GetAttribute('xformOp:translate') if not translate_op: UsdGeom.Xformable(instancer).AddTranslateOp() translate_op.Set((-0.5,) * 3, time=time) # Create a primvar to record the voxelgrid size prim = stage.GetPrimAtPath(instancer.GetPath()) pv = UsdGeom.PrimvarsAPI(prim).CreatePrimvar('grid_size', Sdf.ValueTypeNames.Int) pv.Set(voxelgrid.size(0)) # Create a primvar to identify the poitn instancer as a Kaolin VoxelGrid pv = UsdGeom.PrimvarsAPI(prim).CreatePrimvar('kaolin_type', Sdf.ValueTypeNames.String) pv.Set('VoxelGrid') return stage
def add_mesh(stage, scene_path, vertices=None, faces=None, uvs=None, face_uvs_idx=None, face_normals=None, time=None): r"""Add a mesh to an existing USD stage. Add a mesh to the USD stage. The stage is modified but not saved to disk. Args: stage (Usd.Stage): Stage onto which to add the mesh. scene_path (str): Absolute path of mesh within the USD file scene. Must be a valid ``Sdf.Path``. vertices (torch.FloatTensor, optional): Vertices with shape ``(num_vertices, 3)``. faces (torch.LongTensor, optional): Vertex indices for each face with shape ``(num_faces, face_size)``. Mesh must be homogenous (consistent number of vertices per face). uvs (torch.FloatTensor, optional): of shape ``(num_uvs, 2)``. face_uvs_idx (torch.LongTensor, optional): of shape ``(num_faces, face_size)``. If provided, `uvs` must also be specified. face_normals (torch.Tensor, optional): of shape ``(num_vertices, num_faces, 3)``. time (int, optional): Positive integer defining the time at which the supplied parameters correspond to. Returns: (Usd.Stage) Example: >>> vertices = torch.rand(3, 3) >>> faces = torch.tensor([[0, 1, 2]]) >>> stage = create_stage('./new_stage.usd') >>> mesh = add_mesh(stage, '/World/mesh', vertices, faces) >>> stage.Save() """ if time is None: time = Usd.TimeCode.Default() usd_mesh = UsdGeom.Mesh.Define(stage, scene_path) if faces is not None: num_faces = faces.size(0) face_vertex_counts = [faces.size(1)] * num_faces faces_list = faces.view(-1).cpu().long().tolist() usd_mesh.GetFaceVertexCountsAttr().Set(face_vertex_counts, time=time) usd_mesh.GetFaceVertexIndicesAttr().Set(faces_list, time=time) if vertices is not None: vertices_list = vertices.cpu().float().tolist() usd_mesh.GetPointsAttr().Set(Vt.Vec3fArray(vertices_list), time=time) if uvs is not None: interpolation = None uvs_list = uvs.view(-1, 2).cpu().float().tolist() pv = UsdGeom.PrimvarsAPI(usd_mesh.GetPrim()).CreatePrimvar( "st", Sdf.ValueTypeNames.Float2Array) pv.Set(uvs_list, time=time) if face_uvs_idx is not None: pv.SetIndices(Vt.IntArray(face_uvs_idx.view(-1).cpu().long().tolist()), time=time) interpolation = 'faceVarying' else: if vertices is not None and uvs.size(0) == vertices.size(0): interpolation = 'vertex' elif uvs.size(0) == faces.size(0): interpolation = 'uniform' elif uvs.size(0) == len(faces_list): interpolation = 'faceVarying' if interpolation is not None: pv.SetInterpolation(interpolation) if face_uvs_idx is not None and uvs is None: raise ValueError('If providing "face_uvs_idx", "uvs" must also be provided.') if face_normals is not None: face_normals = face_normals.view(-1, 3).cpu().float().tolist() usd_mesh.GetNormalsAttr().Set(face_normals, time=time) UsdGeom.PointBased(usd_mesh).SetNormalsInterpolation('faceVarying') return usd_mesh.GetPrim()