Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HdSt instancing does not handle different orientation, doubleSided, and/or mirror transform #1190

Closed
spitzak opened this issue Apr 30, 2020 · 20 comments

Comments

@spitzak
Copy link

spitzak commented Apr 30, 2020

Description of Issue

Instancing seems to get confused about various settings of the instances in usdview. Example file renders quite different depending on whether instancing is enabled or not.

Steps to Reproduce

  1. View usd file (in comment)
    newcubesgl
  2. Edit to comment out the instanceable to see expected result.
    hdst_instancing_off

System Information (OS, Hardware)

Linux

Package Versions

USD 20.3

@spitzak
Copy link
Author

spitzak commented Apr 30, 2020

#usda 1.0

# orientation does not work for Cube, bug sent to pixar
#def Cube "cube"
#{
#    double size = 2
#    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
#    uniform token[] xformOpOrder = ["xformOp:transform"]
#}

def Xform "cube" (
    instanceable = true
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
    uniform token[] xformOpOrder = ["xformOp:transform"]
def Mesh "cube"
{
    float3[] extent = [(-1, -1, -1), (1, 1, 1)]
    int[] faceVertexCounts = [4, 4, 4, 4, 4]
    int[] faceVertexIndices =  [0, 1, 2, 3, 4, 5, 6, 7, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
    float3[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
    uniform token subdivisionScheme = "none"
}
}

def "cubeMirror" (
    append references = </cube>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, 0, 1) )
}

def "cubeLeftHanded" (
    append references = </cube>
) {
    def "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, 0, 1) )
}

def "cubeLeftHandedMirror" (
    append references = </cubeLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, 0, 1) )
}

################

def "cubeNormals" (
    append references = </cube>
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -3, 1) )
    def "cube" {
    normal3f[] primvars:normals = [(0,0,1), (0,0,-1), (0,-1,0), (1,0,0), (-1,0,0)] (
        interpolation = "uniform"
    )
}
}

def "cubeNormalsMirror" (
    append references = </cubeNormals>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -3, 1) )
}

def "cubeNormalsLeftHanded" (
    append references = </cubeNormals>
) {
    def "cube" {
        uniform token orientation = "leftHanded"
        normal3f[] primvars:normals = [(0,0,-1), (0,0,1), (0,1,0), (-1,0,0), (1,0,0)] (
            interpolation = "uniform"
        )
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -3, 1) )
}

def "cubeNormalsLeftHandedMirror" (
    append references = </cubeNormalsLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -3, 1) )
}

################

def "cubeDoubleSided" (
    append references = </cube>
) {
    def "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -6, 1) )
}

def "cubeDoubleSidedMirror" (
    append references = </cubeDoubleSided>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHanded" (
    append references = </cubeDoubleSided>
) {
    def "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHandedMirror" (
    append references = </cubeDoubleSidedLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -6, 1) )
}

################

def "cubeDoubleSidedNormals" (
    append references = </cubeNormals>
) {
    def "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsMirror" (
    append references = </cubeDoubleSidedNormals>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHanded" (
    append references = </cubeNormalsLeftHandled>
) {
    def "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHandedMirror" (
    append references = </cubeDoubleSidedNormalsLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -9, 1) )
}

################

def Mesh "plane"
{
    int[] faceVertexCounts = [4]
    int[] faceVertexIndices =  [0, 1, 2, 3]
    float3[] points = [(-3, -1.1, 1.5), (9,-1.1,1.5), (9,-1.1,-10.5), (-3,-1.1,-10.5)]
    color3f[] primvars:displayColor = [(1, 0, 0), (1, 0, 1), (1, 0, 0), (1, 0, 1)] (
        interpolation = "vertex"
    )
    uniform token subdivisionScheme = "none"
}

@spitzak
Copy link
Author

spitzak commented May 1, 2020

I have updated the sample code and example images with corrections to the normals in the NormalsLeftHanded cubes. This actually made the render worse.

@jilliene
Copy link

jilliene commented May 4, 2020

Filed as internal issue #USD-6035

@spiffmon
Copy link
Member

spiffmon commented May 5, 2020

Hi @spitzak ,
We are working through your observations, but many of the examples you provide are, in fact, illegal/malformed USD. When you define an instance of something else through referencing/composition, you can only override properties of the root instance prim. Any nested primSpecs inside/under the instanced prim will be ignored by the UsdStage. S prims like , , etc. are not going to behave as you expect them to. subeLeftHanded will not be left-handed, etc.

--spiff

@spitzak
Copy link
Author

spitzak commented May 6, 2020

I only added the parent because I was told that instanceable does not work unless the prim is an XForm. Is this true?

@spitzak
Copy link
Author

spitzak commented May 6, 2020

Yep: removing the Xform and making the Cube be instanceable produces these:

Warning: in _Populate at line 278 of pxr/usdImaging/usdImaging/instanceAdapter.cpp -- The gprim at path </__Master_4> was directly instanced. In order to instance this prim, put the prim under an Xform, and instance the Xform parent.
I am unclear what is happening here. It is clearly creating 8 master cubes, implying they each are instanced twice, I would assume for the normal and mirror transforms. If what you describe is correct it would produce one master cube.

@spitzak
Copy link
Author

spitzak commented May 6, 2020

New version with typos fixed and "def" replaced with "over". Loading the usd file creates 8 masters for all the arrangements, but for some reason the instancers are not populated with these correctly in usdview. Also it is proposed that this file is incorrect, but from the description it should then produce 1 master and a single instancer for all 16 copies.

#usda 1.0

# orientation does not work for Cube, bug sent to pixar
#def Cube "cube"
#{
#    double size = 2
#    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
#    uniform token[] xformOpOrder = ["xformOp:transform"]
#}

def Xform "cube" (
    instanceable = true
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
    uniform token[] xformOpOrder = ["xformOp:transform"]
def Mesh "cube"
{
    float3[] extent = [(-1, -1, -1), (1, 1, 1)]
    int[] faceVertexCounts = [4, 4, 4, 4, 4]
    int[] faceVertexIndices =  [0, 1, 2, 3, 4, 5, 6, 7, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
    float3[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
    uniform token subdivisionScheme = "none"
}
}

def "cubeMirror" (
    append references = </cube>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, 0, 1) )
}

def "cubeLeftHanded" (
    append references = </cube>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, 0, 1) )
}

def "cubeLeftHandedMirror" (
    append references = </cubeLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, 0, 1) )
}

################

def "cubeNormals" (
    append references = </cube>
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -3, 1) )
    over "cube" {
    normal3f[] primvars:normals = [(0,0,1), (0,0,-1), (0,-1,0), (1,0,0), (-1,0,0)] (
        interpolation = "uniform"
    )
}
}

def "cubeNormalsMirror" (
    append references = </cubeNormals>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -3, 1) )
}

def "cubeNormalsLeftHanded" (
    append references = </cubeNormals>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
        normal3f[] primvars:normals = [(0,0,-1), (0,0,1), (0,1,0), (-1,0,0), (1,0,0)] (
            interpolation = "uniform"
        )
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -3, 1) )
}

def "cubeNormalsLeftHandedMirror" (
    append references = </cubeNormalsLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -3, 1) )
}

################

def "cubeDoubleSided" (
    append references = </cube>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -6, 1) )
}

def "cubeDoubleSidedMirror" (
    append references = </cubeDoubleSided>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHanded" (
    append references = </cubeDoubleSided>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHandedMirror" (
    append references = </cubeDoubleSidedLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -6, 1) )
}

################

def "cubeDoubleSidedNormals" (
    append references = </cubeNormals>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsMirror" (
    append references = </cubeDoubleSidedNormals>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHanded" (
    append references = </cubeNormalsLeftHanded>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHandedMirror" (
    append references = </cubeDoubleSidedNormalsLeftHanded>
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -9, 1) )
}

################

def Mesh "plane"
{
    int[] faceVertexCounts = [4]
    int[] faceVertexIndices =  [0, 1, 2, 3]
    float3[] points = [(-3, -1.1, 1.5), (9,-1.1,1.5), (9,-1.1,-10.5), (-3,-1.1,-10.5)]
    color3f[] primvars:displayColor = [(1, 0, 0), (1, 0, 1), (1, 0, 0), (1, 0, 1)] (
        interpolation = "vertex"
    )
    uniform token subdivisionScheme = "none"
}

@spiffmon
Copy link
Member

spiffmon commented May 6, 2020 via email

@spitzak
Copy link
Author

spitzak commented May 6, 2020

Yes that is the behavior I expected, I certainly want it to only instance prims together if they match. And it does look like usd creates 8 master prims with the correct settings.

However either the prototype references are wrong in the usd data, or there is a mistake in the usdImaging front end that turns these into instancer bprims, because the resulting cubes are pretty random.

@spiffmon
Copy link
Member

spiffmon commented May 6, 2020

I'm posting what I argue is a "correct" version of your example, removing instancing from the "intermediate" prims that won't actually reflect their contained scene description as instances... you still get eight masters, just only one instance of each, plus eight non-instancced cubes. We'll work from this version (plus the version of it where everyhting is uninstanced).

I do see differences between the instanced and uninstanced versions, so there is something for us to dig into here! Looks like you have backface culling enabled?

#usda 1.0
(
   upAxis = "Y"
)

# orientation does not work for Cube, bug sent to pixar
#def Cube "cube"
#{
#    double size = 2
#    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
#    uniform token[] xformOpOrder = ["xformOp:transform"]
#}

def Xform "cube" (
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, 0, 1) )
    uniform token[] xformOpOrder = ["xformOp:transform"]
def Mesh "cube"
{
    float3[] extent = [(-1, -1, -1), (1, 1, 1)]
    int[] faceVertexCounts = [4, 4, 4, 4, 4]
    int[] faceVertexIndices =  [0, 1, 2, 3, 4, 5, 6, 7, 4, 7, 3, 2, 0, 3, 7, 6, 4, 2, 1, 5]
    float3[] points = [(1, 1, 1), (-1, 1, 1), (-1, -1, 1), (1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1)]
    uniform token subdivisionScheme = "none"
}
}

def "cubeMirror" (
    append references = </cube>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, 0, 1) )
}

def "cubeLeftHanded" (
    append references = </cube>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, 0, 1) )
}

def "cubeLeftHandedMirror" (
    append references = </cubeLeftHanded>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, 0, 1) )
}

################

def "cubeNormals" (
    append references = </cube>
) {
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -3, 1) )
    over "cube" {
    normal3f[] primvars:normals = [(0,0,1), (0,0,-1), (0,-1,0), (1,0,0), (-1,0,0)] (
        interpolation = "uniform"
    )
}
}

def "cubeNormalsMirror" (
    append references = </cubeNormals>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -3, 1) )
}

def "cubeNormalsLeftHanded" (
    append references = </cubeNormals>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
        normal3f[] primvars:normals = [(0,0,-1), (0,0,1), (0,1,0), (-1,0,0), (1,0,0)] (
            interpolation = "uniform"
        )
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -3, 1) )
}

def "cubeNormalsLeftHandedMirror" (
    append references = </cubeNormalsLeftHanded>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -3, 1) )
}

################

def "cubeDoubleSided" (
    append references = </cube>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -6, 1) )
}

def "cubeDoubleSidedMirror" (
    append references = </cubeDoubleSided>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHanded" (
    append references = </cubeDoubleSided>
) {
    over "cube" {
        uniform token orientation = "leftHanded"
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -6, 1) )
}

def "cubeDoubleSidedLeftHandedMirror" (
    append references = </cubeDoubleSidedLeftHanded>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -6, 1) )
}

################

def "cubeDoubleSidedNormals" (
    append references = </cubeNormals>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsMirror" (
    append references = </cubeDoubleSidedNormals>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHanded" (
    append references = </cubeNormalsLeftHanded>
) {
    over "cube" {
        uniform bool doubleSided = 1
    }
    matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (4.5, 0, -9, 1) )
}

def "cubeDoubleSidedNormalsLeftHandedMirror" (
    append references = </cubeDoubleSidedNormalsLeftHanded>
    instanceable = true
) {
    matrix4d xformOp:transform = ( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (7.5, 0, -9, 1) )
}

################

def Mesh "plane"
{
    int[] faceVertexCounts = [4]
    int[] faceVertexIndices =  [0, 1, 2, 3]
    float3[] points = [(-3, -1.1, 1.5), (9,-1.1,1.5), (9,-1.1,-10.5), (-3,-1.1,-10.5)]
    color3f[] primvars:displayColor = [(1, 0, 0), (1, 0, 1), (1, 0, 0), (1, 0, 1)] (
        interpolation = "vertex"
    )
    uniform token subdivisionScheme = "none"
}

@spitzak
Copy link
Author

spitzak commented May 6, 2020

That produces 16 cubes (8 of which are "instances" but each cube is only drawn once). Would prefer a test where the same cube is instanced twice, with different signs of the xform matrix. As far as I can tell that can only be achieved if all 16 cubes have "instanceable" true.

Now I'm thinking the correct method is to put "instanceable" on the parent xform, but rather than copy the parent xform, each cube is a new xform, also with "instanceable" turned on, and the cube inside it is a reference. Would this work?

In the screen shot above I have "cull backfaces" turned on. If I turn it off I get black for the invisible faces.

@spitzak
Copy link
Author

spitzak commented May 6, 2020

Can something be done with github so that attachements of usd (or at least usda) files is allowed? I have to keep posting my usd files as comments.

@c64kernal
Copy link
Contributor

Hey @spitzak -- does it work if you gzip them real quick first?

@spiffmon
Copy link
Member

spiffmon commented May 6, 2020

You could achieve that in a way that wouldn't be confusing by "defining" all 8 protos as "pure overs" instead of defs (for the root Xform prims), and then creating 16 instanceable defs that each only override the root transform

@spitzak
Copy link
Author

spitzak commented May 7, 2020

It is unfortunate if this is devolving into a question about instancing, but I did not understand what you are saying in previous comment, and I have been trying all kinds of experiments with the most simplistic setups possible and have been unable to convince usd to make two identical objects into instances.

What I am trying is a usd file that looks like this (with question marks replacing the parts that I am unsure of):

def Xform prim1 (
   instanceable = true
)
{
    def Mesh cube { ... }
    ????
}

def Xform prim2 (
   ????
)
{
    matrix4d xformOp:transform = (...)
    ????
}

And then trying as hard as I can to convince usd that these two Xforms are identical and should be instanced so there is ONE master, two instances of that master, and ZERO "normal" prims. Everything I try gives me a normal prim, and a single master that is instanced exactly once (which seems counter-productive as this is more complex than if there were just two prims).

The closest I have ever gotten is the last example I posted of 16 cubes. Here there are the expected 8 masters all with the correct settings. And there is only one unnecessary "non-instanced" cube (the first one that all the others reference). However for each instance, the "master" that is referenced seems almost random, this seems to be the underlying bug, it is in usd itself, not usdImaging.

@spiffmon
Copy link
Member

spiffmon commented May 7, 2020

There is a fundamental requirement of native instancing that an instance must have one or more direct composition arcs. Bill, can you please read (it's short) http://graphics.pixar.com/usd/docs/USD-Glossary.html#USDGlossary-Instanceable and let me know if it helps? Here's one example of what I was trying to suggest in my last post, using your new smaller example - there are many patterns for doing this "master-protos and instances all in the same layer"... I believe this one may have come from Luma:

#usda 1.0
(
    upAxis = "Y"
)

def "Prototypes" (
    # when exporting, you'd deactivate this prim just before saving the Stage
    active = false
)
{
    def Xform "ProtoMesh1" (
        instanceable = true
    )
    {
        def Mesh "cube"
        {   # define the cube
        }
    }
    # Other prototypes can go here
}

def Xform "instance1" (
   references = </Prototypes/ProtoMesh1>
)
{
    # override xform, but that's about it
}

def Xform "instance2" (
   references = </Prototypes/ProtoMesh1>
)
{
    # override xform, but that's about it
}

AFAWK, there are no bugs in USD's algorithm for choosing masters for all the true instances on your stage. Hopefully this gets you on the right track!

@spitzak
Copy link
Author

spitzak commented May 7, 2020

Thanks, it was the "active = false" that I was missing to hide the prototype. I was trying to use "class" to make it hidden and not having any luck.

@spitzak
Copy link
Author

spitzak commented May 7, 2020

cubesInstancd2.usda.gz

That produces the correct arrangement though I am not absolutely certain the fact that my prototypes refer to other prototypes that have instanceable set is valid. Hydra GL still renders this wrong, though I am happy to report that our in-house renderer is doing the correct thing.

It would be very helpful if referring to an instanceable prim and then overriding stuff either made a real copy, or caused an error.

@spiffmon
Copy link
Member

spiffmon commented May 7, 2020

Glad you got what you were after, Bill! In our own pipeline, at least, we believe it's way too easy (due to the nature of referencing and sharing) to unintentionally accumulate overrides on instanced prims/sub-trees, and therefore that making a copy (new master) when we encounter them would often seriously degrade the sharing you'd get from instancing... and even detecting them properly would add non-trivial per-instance expense when composing the stage.

We did discuss with our internal working group, back when we designed native instancing, whether it should be an error to have overrides on an instance. A compelling argument was made about the usefulness of allowing them, to be ignored. It's about experimentation and preserving your work. I have a bunch of instances, and I want to try customizing one of them; so I uninstance it, make a bunch of overrides, but then decide it's not worth it (or not needed) at this point, so I just re-instance the thing... and my edits are still there, if I want to revisit the decision later.

I haven't asked around about whether this behavior is being intentionally used to good effect, but given the "unintentional overrides" I mentioned, I suspect we might need to change some of the ways we work, were we to turn overrides into errors. But it is something we could discuss.

@spitzak
Copy link
Author

spitzak commented May 7, 2020

Okay, yes it seems like real production scenes won't do this.

I am wondering if in fact the way I did the prototoypes is wrong. It is producing the correct result, but I am still referencing a prim that has instancing=true and the overriding things.

And I am pretty certain hdSt is rendering the result incorrectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants