Solaris USD PointInstancer - lopimport rotation issue

   1687   1   2
User Avatar
Member
39 posts
Joined: Jan. 2012
Offline
I am seeing a discrepancy in rotations when USD PointInstancers are converted to sops using the lopimport SOP. As the rotations approach the poles of a circle, I can see a small shift between lops/sops.

I believe I have tracked this back to the ComputeInstanceTransformsAtTime method of the PointInstancer, as I can re-create this using an inlinelop and a pythonlop.

Here I have some USD representing a smaller section of a circle, instancing a simple box. Pop this into the inlinelop.

#sdf 1.4.32

def PointInstancer "my_instancer"
{
    int64[] invisibleIds = []
    quath[] orientations = [(0.998535, 0, 0, -0.0565186), (0.999023, 0, 0, -0.0439758), (0.999512, 0, 0, -0.0314026), (1, 0, 0, -0.0188446), (1, 0, 0, -0.00628281), (1, 0, 0, 0.00628281), (1, 0, 0, 0.0188446), (0.999512, 0, 0, 0.0314026), (0.999023, 0, 0, 0.0439758), (0.998535, 0, 0, 0.0565186)]
    point3f[] positions = [(-8.911743, 0.5044851, 0), (-6.937198, 0.30531064, 0), (-4.9582753, 0.15582031, 0), (-2.9762185, 0.05610727, 0), (-0.99228066, 0.006234976, 0), (0.99228066, 0.006234976, 0), (2.976217, 0.056106895, 0), (4.958278, 0.15581957, 0), (6.9371996, 0.30531064, 0), (8.911743, 0.5044858, 0)]
    int[] protoIndices = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    rel prototypes = </my_instancer/Prototypes/Root>

    def Scope "Prototypes"
    {
        def Xform "Root" (
        )
        {
            def Cube "cube" (
            )
            {
                double size = 2
            }
        }
    }
}

Here is a snippet to go into a pythonlop iterating over the instances, and grabbing the matrix from the point, and applying it to the new prims Xform. If I compare their orients after this, I can see a small discrepancy near the pole.

node = hou.pwd()
stage = node.editableStage()

import pxr

prim = stage.GetPrimAtPath("/my_instancer")
instancer = pxr.UsdGeom.PointInstancer(prim)

orients = instancer.GetOrientationsAttr().Get()
xforms = instancer.ComputeInstanceTransformsAtTime(pxr.Usd.TimeCode.Default(), pxr.Usd.TimeCode.Default())

for index, xform in enumerate(xforms):
    xform_prim = pxr.UsdGeom.Xform.Define(stage, '/cube_grp{}'.format(index))
    cube_prim = pxr.UsdGeom.Cube.Define(stage, '/cube_grp{}/cube'.format(index))
    cube_prim.GetDisplayColorAttr().Set([(1, 0, 0)])
    xform_prim.AddTransformOp(opSuffix="from_instancer").Set(xform)

    prim_orient = xform_prim.GetLocalTransformation().ExtractRotation().GetQuat()
    prim_quat_h = pxr.Gf.Quath(prim_orient)
    
    # I have converted the Quatd to a Quath to match the types
    print "xform prim orient:"
    print prim_quat_h
    print "instancer point orient:"
    print orients[index]
    
    match = prim_quat_h == orients[index]
    # This will error
    assert match == True

you will see a small shift in the rotation, and the angle between the 2 quaternions is slightly off. If you use a lopimport sop in SOPS, you will also visually see the shift as I have colored the prims red. Is this something that will first need to be fixed on the USD side? Or is this something to do with the formatting of the orientations?

Cheers,
Aaron.
www.aaronauty.com
User Avatar
Member
120 posts
Joined: Jan. 2012
Offline
Did you try normalizing quaternions ?

I have seen few Issues at Pixar USD repo about this issue. Don't remember specifics, but I think USD doesnt normalize quat, where other DCCs and renderers do.

Just a thought.
Michal Tas Maciejewski @ www.vfxtricks.com
  • Quick Links