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

Indexed normal primvars with normal3d type causes incorrect rendering #2070

Closed
qnzhou opened this issue Oct 21, 2022 · 7 comments
Closed

Indexed normal primvars with normal3d type causes incorrect rendering #2070

qnzhou opened this issue Oct 21, 2022 · 7 comments

Comments

@qnzhou
Copy link

qnzhou commented Oct 21, 2022

Description of Issue

When using indexed primvar to store faceVarying normals with normal3d type, usdview does not produce the correct rendering.

Steps to Reproduce

Here is a simple cube usda file to reproduce the problem:

#usda 1.0
(
    defaultPrim = "tmp_example"
    doc = "Example to reproduce the bug."
    metersPerUnit = 0.01
    upAxis = "Y"
)

def Xform "tmp_example"
{
    def Mesh "tmp_example_mesh"
    {
        int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
        int[] faceVertexIndices = [1, 2, 0, 3, 6, 2, 7, 4, 6, 5, 0, 4, 6, 0, 2, 3, 5, 7, 1, 3, 2, 3, 7, 6, 7, 5, 4, 5, 1, 0, 6, 4, 0, 3, 1, 5]
        point3f[] 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)]
        normal3d[] primvars:normals = [(-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (0, 0, -1), (0, 0, -1), (0, 0, -1), (1, 0, 0), (1, 0, 0), (1, 0, 0), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (-1, 0, 0), (0, 0, -1), (1, 0, 0), (0, 0, 1), (0, -1, 0), (0, 1, 0)] (
            interpolation = "faceVarying"
        )
        int[] primvars:normals:indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 18, 1, 3, 19, 4, 6, 20, 7, 9, 21, 10, 12, 22, 13, 15, 23, 16]
        uniform token subdivisionScheme = "none"
    }
}

Running usdview tmp.usda yields the following incorrect result:
image

Interestingly, changing normal3d to normal3f fixes the problem.

System Information (OS, Hardware)

MacOS 10.15.7

Package Versions

v22.8

Build Flags

Default.

@dpmacri
Copy link

dpmacri commented Oct 21, 2022

Hi Qingnan,

I'm not sure why changing to normal3f fixes things, but the reason it's not rendering correctly with normal3d is that you have too many normal indices. There should be 1 normal index per face and there should be as many indices as there are faces. Here's a modified version of your file that works correctly for both normal3d and normal3f.

#usda 1.0
(
defaultPrim = "tmp_example"
doc = "Example to reproduce the bug."
metersPerUnit = 0.01
upAxis = "Y"
)

def Xform "tmp_example"
{
def Mesh "tmp_example_mesh"
{
int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
int[] faceVertexIndices = [1, 2, 0, # Face 0
3, 6, 2, # Face 1
7, 4, 6, # Face 2
5, 0, 4, # Face 3
6, 0, 2, # Face 4
3, 5, 7, # Face 5
1, 3, 2, # Face 6
3, 7, 6, # Face 7
7, 5, 4, # Face 8
5, 1, 0, # Face 9
6, 4, 0, # Face 10
3, 1, 5] # Face 11
point3f[] 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)]
# Note there are the same number of normals now as there are faces
normal3d[] primvars:normals = [(-1, 0, 0), (-1, 0, 0),
( 0, 0, -1), ( 0, 0, -1),
( 1, 0, 0), ( 1, 0, 0),
( 0, 0, 1), ( 0, 0, 1),
( 0, -1, 0), ( 0, -1, 0),
( 0, 1, 0), ( 0, 1, 0)] (
interpolation = "faceVarying"
)
# Each normal index corresponds to a face
int[] primvars:normals:indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
uniform token subdivisionScheme = "none"
}
}

@qnzhou
Copy link
Author

qnzhou commented Oct 21, 2022

There should be 1 normal index per face and there should be as many indices as there are faces.

Is this true? To produce smooth shading everywhere except at sharp creases, it is often necessary to provide a per-face-vertex normal instead of a single normal for the entire face. I think face varying indexed primvars are designed for this purposes, otherwise we can just uniform primvars instead.

@dpmacri
Copy link

dpmacri commented Oct 21, 2022

I'm not an expert :-). But you had explicitly set "faceVarying" as the interpolation method, so I made changes to align with that. If you really intended different normals per vertex, I think the interpolation needs to be either "uniform" or "vertex" but then you'll still need to make some changes to the number of normals and indices.

@spiffmon
Copy link
Member

@qnzhou is correct - faceVarying interpolation means providing a value per face-vertex. The interpolation names are not awesome - it means "varying across each face, independently", not "varying per-face", which is, as stated, uniform interpolation. While I am mildly surprised that double-precision normals do not seem to be working, I'm also quite curious what scenario actually benefits from double-precision normals (even in geometry processing) when the points themselves, which can have alot more variance, assuming your normals are close to unit length) are mandatorily single-precision?

At production-scale, we gain quite alot of network/bandwidth/memory savings from single precision, relying on double-precision transforms to position primitives with fidelity.

@dpmacri
Copy link

dpmacri commented Oct 22, 2022

Thanks @spiffmon ! I always seem to get those interpolations backwards :-(

@qnzhou
Copy link
Author

qnzhou commented Oct 22, 2022

Thanks @spiffmon ! I assume you are able to reproduce the bug. I choose normal3d simply because the data I have is using double. I agree that normal3f is probably sufficient in practice. With that said, it is often beneficial to save geometry data in its full precision at least for debugging purposes.

@tallytalwar
Copy link
Contributor

Filed as internal issue #USD-7728

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

4 participants